Creando una aventura conversacional (I)

Ha llegado el momento de hacer algo útil con la librería y, para ello, damos nuestros primeros pasos creando una sencilla aventura conversacional. Está claro que siempre existirán alternativas mejores para la creación de este tipo de aventuras en nuestro Spectrum (el PAWS, sin ir más lejos, u otros parsers). Sin embargo, una aventura conversacional puede ser un ejemplo didáctico sencillo y a la vez atractivo… ¡estaremos programando un juego desde un primer momento! Más adelante ya hablaremos de sprites, movimiento, colisiones, etc.

Como todo buen creador de aventuras conversacionales sabe, el primer paso para crear algo que interese al jugador es tener una buena historia de transfondo; sin ella, la aventura pierde interés. Debemos huir del típico argumento de salvar una princesa o conseguir un tesoro, y pensar en algo original. También debemos pensar en el tipo de público al que se dirige la aventura, entre otras cosas.

Como lo que tratamos de hacer nosotros es una aventura de ejemplo, que nos sirva para practicar con el z88dk, está claro que buscaremos sencillez; sencillez en la historia a contar, en el número de habitaciones a visitar y objetos con los que interactuar. Así pues, nuestra (poco original) historia es la siguiente:

Guybrush Threepwood quiere ser pirata. Para ello se ha dirigido a la isla de Melêe, donde le han dicho que un maestro le puede enseñar a serlo. La historia comienza en la taberna de la Isla de Melêe, donde Guybrush deberá buscar al maestro e impresionarlo con algún truco para que acepte enseñarle todo lo que sabe.

Con este sencillo guión inicial pretendemos construir una aventura con no más de seis habitaciones, tres objetos con los que interactuar, y un personaje pseudo-inteligente o PSI. Para ello haremos uso de la librería z88dk. Iremos viendo que, salvo algunas peculiaridades, es como si estuvieramos programando una aventura conversacional en modo texto en C para un PC actual, ya que nos limitaremos a hacer uso de las librerías stdio.h y string.h incluidas con z88dk, muy parecidas a sus contrapartidas en el mundo de los compiladores estándar actuales. Así pues, comencemos.

Por supuesto, el primer paso es tener z88dk instalado tal como se comentó en artículos anteriores. Lo siguiente es crear un entorno de trabajo donde tengamos el código fuente de nuestro juego conforme lo desarrollemos. Así pues, creamos un nuevo directorio allá donde queramos, para almacenarlo. No es necesario que el directorio se encuentre dentro de la carpeta donde hubiésemos instalado el z88dk, pues si le damos el valor correcto a las variables de entorno (por ejemplo, ejecutando el setpath.h que se propuso en la primera entrega de z88dk) podremos trabajar en cualquier lugar de nuestro disco duro.

Dentro de ese directorio de trabajo tendremos que crear los siguientes archivos:

  • aventura.c: será el fichero que contendrá el código principal de nuestro juego, y por lo tanto, el método main.
  • datos.h: un archivo de cabecera que utilizaremos para definir las estructuras de datos que se utilizarán para la creación de la aventura.
  • y, opcionalmente, un archivo Makefile, si utilizamos la herramienta GNU Make para la construcción automática de nuestro programa.

En el caso de que no utilicemos Make, cada vez que queramos compilar el programa y probarlo con un emulador, deberemos teclear lo siguiente:

zcc +zxansi -vn -o aventura.bin aventura.c -lndos
bin2tap aventura.bin aventura.tap

El parámetro +zxansi indica que se trata de un programa de solo texto para un Spectrum. El parámetro -vn desactiva el modo verbose, lo cual quiere decir que se nos mostrará la mínima información posible por pantalla durante el proceso de compilación. Y -lndos le dice al compilador zcc que enlace con los archivos de librería adecuados cuando hacemos uso de stdio.h y string.h (no tiene nada que ver con el sistema operativo MS-DOS).

Sin embargo, si disponemos de la utilidad Make, podemos crear un archivo Makefile como el siguiente:

all: aventura.tap

aventura.tap: aventura.bin
    bin2tap aventura.bin aventura.tap

aventura.bin: aventura.c
    zcc +zxansi -vn -o aventura.bin aventura.c -lndos

y ejecutar 'make' en el mismo directorio donde se encuentre este archivo Makefile cada vez que cambiemos el archivo aventura.c y queramos compilar.

Para tener claro como va a ser el entorno de juego, es necesario dibujar un mapa. En dicho mapa deben estar claras cúales van a ser las localizaciones o habitaciones por las que va a poder desplazarse el jugador, y cómo van a estar conectadas entre sí. En el caso de nuestro ejemplo concreto, vamos a crear un mapa de la taberna de la isla de Melêe, en donde Guybrush, nuestro personaje, buscará a un maestro de piratería. Un mapa perfectamente válido podría ser el siguiente:

Nuestro mapa

Como vemos, cada habitación está numerada. Esto es muy importante, luego veremos por qué. Las líneas que unen dos habitaciones adyacentes indican que dichas habitaciones están comunicadas; esto quiere decir que desde una habitación podremos acceder a la otra y viceversa. Además de dibujar el mapa, debemos escribir una descripción para cada habitación. Para nuestra aventura concreta, podríamos usar las siguientes descripciones:

  • Habitación 1: “Te encuentras en la entrada de la taberna de Melêe Island. Desde aquí puedes oler los vómitos de los borrachos que vas a encontrar en su interior.”
  • Habitación 2: “Las sombras del callejón en el que te encuentras te sobrecogen. Estás rodeado de montones de basura.”
  • Habitación 3: “Estás en uno de los dormitorios de la taberna. Varias literas están alineadas, permitiendo a muchos piratas dormir juntos en una misma habitación.”
  • Habitación 4: “El salón principal de la taberna. Decenas de piratas se encuentran aquí bebiendo, cantando, peleándose, vomitando, y metiendo mano a las doncellas del lugar. Si te diriges al norte, este u oeste podrás visitar varias de las habitaciones del local.”
  • Habitación 5: “Una gran cantidad de pucheros sucios están amontonados en la cocina. Platos a medio comer, jarras medio llenas, y cubiertos sucios les hacen compañía.”
  • Habitación 6: “Tras apartar una cortina accedes a un reservado. Es una zona exclusiva de la taberna a donde muy pocos piratas pueden acceder.”

Una vez se ha realizado el diseño, es hora de realizar una implementación de todo esto. Debemos crear una estructura de datos que nos permita almacenar la información sobre las habitaciones. Podemos incluir el siguiente código dentro de datos.h:

typedef struct
{
    int id;
    char descripcion[255];
    int direcciones[4];
            // 0 - Norte
            // 1 - Este
            // 2 - Sur
            // 3 - Oeste
} THabitacion;

La estructura THabitacion es la que nos va a permitir disponer de la información de las habitaciones de una forma ordenada. Cada uno de los campos va a ser utilizado para lo siguiente:

  • id: identificador de la habitación. Cada habitación debe estar numerada desde el 1 en adelante, tal como se hizo con el mapa a la hora de diseñar la aventura. Es en este campo donde introduciremos el número de la habitación indicado en el mapa; en nuestro ejemplo particular, el id de la entrada a la taberna sería el 1, el id del callejón valdría 2, etc. En nuestra implementación es inútil, y además ocupa memoria (algo de lo que nuestro Spectrum no anda demasiado sobrado), pero se incluye a efectos ilustrativos.
  • descripcion: una cadena de texto que contendrá la descripción de la habitación que será mostrada al jugador durante la aventura. Podemos usar los textos anteriormente indicados, teniendo en cuenta que no podremos utilizar tildes ni eñes (ni tampoco el acento circunflejo en el nombre de la isla de Melêe).
  • direcciones: un array de cuatro elementos, representando cada uno de esos elementos una dirección concreta. En la posición 0 almacenaremos el identificador de la habitación hacia la que avanzaremos si nos desplazamos hacia el norte, en la posición 1 el identificador de la habitación hacia la que avanzaremos si nos desplanzamos hacia el este, en la posición 2 el identificador de la habitación hacia la que avanzaremos si nos desplazamos hacia el sur, y en la posición 3 el identificador de la habitación hacia la que avanzaremos si nos desplazamos hacia el oeste. Si no es posible desde la habitación desplazarse en algnuna de las direcciones especificadas, deberíamos almacenar el valor 0, indicando que no es posible que el jugador se mueva en esa dirección. Por supuesto, si quisieramos hacer una aventura más compleja con más direcciones de movimiento posibles, podríamos aumentar el tamaño de este array.

Ahora que ya tenemos nuestra estructura de datos que almacenará la información de las habitaciones, es hora de crearlas; ¡vamos a comenzar a programar!

Antes de nada, deberemos introducir las sentencias #include adecuadas en aventura.c; concretamente, al comienzo de nuestro archivo deberemos teclear lo siguiente:

#include "datos.h"
 
#include <stdio.h>
#include <string.h>

El primer include (datos.h) nos permite utilizar las estructuras de datos creadas en nuestro archivo datos.h. Se usan comillas porque es un archivo que se encuentra en el mismo directorio que aventura.c. Los siguientes includes nos proporcionan los métodos de entrada y salida y manipulación de cadenas de z88dk, que son los que vamos a utilizar en nuestro programa. Se introducen entre símbolos de mayor y menor para hacer ver al compilador que se deben buscar estos archivos de cabecera en la ubicación especificada por las variables de entorno y no en el mismo directorio que aventura.c.

Creamos nuestra primera función main, dentro de aventura.c, de la siguiente manera:

void main(void)
{
    int habitacion = 0;
 
    THabitacion habitaciones[6];
    inicializarHabitaciones(habitaciones);
 
    escribirDescripcion(habitaciones,habitacion);
}

Hemos declarado una variable llamada habitaciones que no es mas que un array de estructuras THabitación. Dicho array tiene seis posiciones, porque seis son las habitaciones de las que va a disponer nuestra aventura. La variable habitación hace referencia a la habitación en la que se encuentra actualmente el jugador. Así pues, si habitación vale 0, significará que nos encontraremos en la habitación con índice 0 del array de habitaciones (recordemos que en C, para un array de tamaño N, la primera posición tiene índice 0 y la última N-1). Así pues, al crear esta variable asignándole el valor 0, significa que el jugador inicialmente comenzará en dicha habitación (la entrada a la taberna de los piratas). Durante el transcurso de la partida, el valor de esta variable cambiará para indicar en que habitación se encuentra el jugador. Es importante destacar que todas las variables locales a una función y que vayan a ser utilizadas en el interior de la misma deben ser declaradas en su inicio. No se pueden declarar variables intercaladas con el código de las funciones (como sucede con el C++).

Evidentemente, si intentamos compilar este código, obtendremos un error, porque hay dos funciones que no hemos implementado: inicializarHabitaciones y escribirDescripcion. La primera la vamos a utilizar para rellenar el array habitaciones con los datos correspondientes a las habitaciones de nuestra aventura. La segunda para mostrar el texto de la habitación en la que se encuentra el personaje por pantalla. La implementación de la primera función podría ser la siguiente (debe teclearse este código antes que la función main):

void inicializarHabitaciones(THabitacion habitaciones[])
{
    habitaciones[0].id = 1;
    strcpy(habitaciones[0].descripcion,"Te encuentras en la entrada\
    de la taberna de Melee Island. Desde aqui puedes oler los vomitos\
    de los borrachos que vas a encontrar en su interior.");
    habitaciones[0].direcciones[0] = 4;
    habitaciones[0].direcciones[1] = 2;
    habitaciones[0].direcciones[2] = 0;
    habitaciones[0].direcciones[3] = 0;
 
    habitaciones[1].id = 2;
    strcpy(habitaciones[1].descripcion,"Las sombras del callejon en el\
    que te encuentras te sobrecogen. Estas rodeado de montones de\
    basura.");
    habitaciones[1].direcciones[0] = 0;
    habitaciones[1].direcciones[1] = 0;
    habitaciones[1].direcciones[2] = 0;
    habitaciones[1].direcciones[3] = 1;
 
    habitaciones[2].id = 3;
    strcpy(habitaciones[2].descripcion,"Estas en uno de los dormitorios\
    de la taberna. Varias literas estan alineadas, permitiendo a muchos\
    piratas dormir juntos en una misma habitacion.");
    habitaciones[2].direcciones[0] = 0;
    habitaciones[2].direcciones[1] = 0;
    habitaciones[2].direcciones[2] = 0;
    habitaciones[2].direcciones[3] = 4;
 
    habitaciones[3].id = 4;
    strcpy(habitaciones[3].descripcion,"El salon principal de la taberna.\
    Decenas de piratas se encuentran aquí bebiendo, cantando, peleandose,\
    vomitando, y metiendo mano a las doncellas del lugar. Si te diriges\
    al norte, este u oeste podras visitar varias de las habitaciones\
    del local.");
    habitaciones[3].direcciones[0] = 6;
    habitaciones[3].direcciones[1] = 3;
    habitaciones[3].direcciones[2] = 1;
    habitaciones[3].direcciones[3] = 5;
 
    habitaciones[4].id = 5;
    strcpy(habitaciones[4].descripcion,"Una gran cantidad de pucheros\
    sucios estan amontonados en la cocina. Platos a medio comer, jarras\
    medio llenas, y cubiertos sucios les hacen compañia.");
    habitaciones[4].direcciones[0] = 0;
    habitaciones[4].direcciones[1] = 4;
    habitaciones[4].direcciones[2] = 0;
    habitaciones[4].direcciones[3] = 0;
 
    habitaciones[5].id = 6;
    strcpy(habitaciones[5].descripcion,"Tras apartar una cortina accedes\
    a un reservado. Es una zona exclusiva de la taberna a donde muy\
    pocos piratas pueden acceder.");
    habitaciones[5].direcciones[0] = 0;
    habitaciones[5].direcciones[1] = 0;
    habitaciones[5].direcciones[2] = 4;
    habitaciones[5].direcciones[3] = 0;
}
 
 (Nota: las cadenas que acaban con \ se deben introducir en una sóla línea, sin partir)

Esta función recibe como parámetro el array de habitaciones, que tiene seis posiciones, y para cada una de dichas posiciones inicializa la habitación correspondiente. Observemos por ejemplo como se inicializa la primera habitación, almacenada en la posición 0 del array. Con habitaciones[0].id = 1 indicamos que el identificador de esa primera habitación es 1. Esto realmente no va a ser utilizado en el código, pero para este ejemplo nos puede permitir ver las cosas más claras. Lo siguiente es, mediante el uso del método strcpy proporcionado por la librería de cadenas de z88dk, asociar la habitación con una cadena de texto que contendrá su descripción. Este método strcpy, al igual que en el C del PC, permite copiar en la cadena pasada como primer parámetro la cadena pasada como segundo parámetro, siempre que en la primera cadena haya espacio suficiente para ello. Las siguiente cuatro líneas almacenan a que habitación llegaremos si nos desplazamos en cada una de las cuatro direcciones posibles. Por ejemplo, si nos desplazamos en la dirección 0 (norte) llegaremos a la habitación 4. Si nos desplazamos en la dirección 1 (Este), llegaremos hasta la habitación 2. Para las direcciones 2 y 3 (sur y oeste) almacenamos el valor 0 indicando que no podemos desplazarnos en dicha dirección. El resto de habitaciones se inicializa de igual forma.

La siguiente función que debemos implementar para que nuestro código compile es escribirDescripcion, que como decíamos, presenta por pantalla la descripción de la habitación actual (aquella cuyo índice se almacena en la variable habitacion). Necesita dos parámetros: el array conteniendo la información de todas las habitaciones, y el índice de la habitación actual. El código de esta función podría ser el siguiente (como en el caso anterior, debe ser introducido en el código antes que el método main):

void escribirDescripcion(THabitacion habitaciones, int habitacion)
{
    printf(habitaciones[habitacion].descripcion);
    printf("\n\n");
    printf("Salidas:");
    if (habitaciones[habitacion].direcciones[0] != 0)
        printf(" %c[4mNorte%c[24m",27,27);
    if (habitaciones[habitacion].direcciones[1] != 0)
        printf(" %c[4mEste%c[24m",27,27);
    if (habitaciones[habitacion].direcciones[2] != 0)
        printf(" %c[4mSur%c[24m",27,27);
    if (habitaciones[habitacion].direcciones[3] != 0)
        printf(" %c[4mOeste%c[24m",27,27);
    printf("\n\n");
}

La primera línea no hace más que mostrar por pantalla la cadena de texto de la habitación actual que está almacenada en el array habitaciones. Se hace uso de printf, proporcionado por la librería de entrada y salida estándar de z88dk. La función printf se utiliza igual que en la librería estándar de C para PC, incluyendo el escape de carácteres como el \n (que introduce un retorno de carro), o la escritura de variables mediante %c, %d, etc.

La siguiente línea introduce dos retornos de carro para hacer el texto más claro, y la siguiente muestra la cadena “Salidas:”, pues además de mostrar por pantalla la descripción de la habitación, vamos a indicar en que direcciones se podrá mover el jugador. Para cada posición del array direcciones para la habitación correspondiente, comprobamos si el valor es cero o no. Recordamos que si el valor era cero significaba que el jugador no podía moverse en esa dirección, y en caso contrario, el valor almacenado era el identificador de la habitación hacia la que nos desplazamos moviéndonos en esa dirección. En el caso de que para una dirección concreta el valor del array sea distinto cero, mostraremos la dirección correspondiente.

Las direcciones son escritas de forma especial. Además de un espacio en blanco al inicio de cada una, para separarlas en el caso de que se muestren varias por pantalla, existen unos carácteres raros al inicio (%c[4m) y al final (%c[24m). Esto es una particularidad de z88dk, y nos permite dar formato al texto. Para indicar que se va a formatear el texto, se introduce el carácter 27 en la cadena (mediante %c), y para el formato en sí mismo, se introduce [Xm, donde X es un código numérico que puede ser:

Valor Estilo
1 texto en negrita
2 texto delgado
4 texto subrayado
7 texto inverso

Si se utiliza 21, 22, 24 y 27 se desactiva el formato correspondiente. Así pues, al escribir una dirección, utilizamos el modo 4 para usar subrayado, y cuando terminamos de escribirla, utilizamos el modo 24 para desactivar el subrayado. Si no hiciéramos esto último, cualquier cosa que escribiéramos a continuación aparecería subrayada. Si usamos [m (sin número entre [ y m), se restaurarán los atributos originales del texto.

Si compilamos y ejecutamos, veremos nuestro primer resultado: se mostrará la descripción de la habitación inicial, y se nos mostrarán las direcciones de salida… y ahí acabará el programa, pues no hemos dicho que haga nada más.

Comienza la aventura

Para añadir interactividad, debemos introducir un intérprete de comandos, que ante los mandatos tecleados por el jugador, haga que pase algo en el juego. Este interprete de comandos consistirá en un bucle infinito en el que leeremos cadenas introducidas por el jugador, y según el valor de dichas cadenas se ejecutarán unas intrucciones u otras.

Para nuestro intérprete de comandos necesitaremos dos variables (que una vez más deben ser declaradas al inicio de la función main):

int final = 0;
char comando[250];
int i;

La primera es una variable que podrá tomar dos valores, 0 y 1. Cuando valga 1, querrá decir que la aventura habrá terminado y que el intérprete de comandos deberá dejar de ejecutarse. En el array de caracteres comando almacenaremos el comando de texto introducido por el jugador mediante el teclado. La variable i no es más que un contador que utilizaremos más adelante.

El intérprete de comandos se ejecutará mientras la variable final valga 0 (lo cual significa que la aventura no ha terminado), pidiendo un comando al usuario. Se comparará la cadena introducida por el usuario con un conjunto de cadenas o comandos que el interprete entenderá. Si la cadena se corresponde con alguno de los comandos entenidos por el programa, se desencadenarán las acciones pertinentes. En caso contrario, se mostrará un mensaje por defecto (del tipo de “No entiendo lo que dices”).

Un ejemplo sencillo de intérprete de comandos que solo entiende los comandos “m” y “mirar” (ambos equivalentes) que borrarán la pantalla y mostrarán de nuevo al descripción de la habitación que nos encontramos se muestra a continuación, en el siguiente método main que deberá ser utilizado en lugar del ejemplo anterior:

void main(void)
{
    int habitacion = 0;
    int final = 0;
    char comando[250];
    int i;
 
    THabitacion habitaciones[6];
    inicializarHabitaciones(habitaciones);
    escribirDescripcion(habitaciones,habitacion);
    while (final == 0)
    {
        printf("Que hago ahora? - ");
        gets(comando);
 
    if (strcmp(comando,"m") == 0 || strcmp(comando,"mirar") == 0)
    {
        for (i=0;i<32;i++)
            printf("\n");
 
        escribirDescripcion(habitaciones,habitacion);
    }
    else
        printf("\n\nNo entiendo lo que dices\n\n");
   }
}

Este intérprete de comandos, que comienza con la sentencia while, se explica a continuación:

  • La instrucción while (final == 0) hace que el código del intérprete de comandos se repita infinitamente, porque el valor de la variable final no va a cambiar.
  • El primer printf indica al usuario que está esperando que introduzca un comando.
  • La instrucción gets, al igual que el equivalente de la librería estándar de C del PC, espera a que el usuario introduzca el comando y lo almacena en la cadena comando, creada anteriormente.
  • El if comprueba si el comando introducido es exactamente igual a alguno de los dos únicos comandos que entiende nuestra aplicación, m y mirar. Para ello se hace uso de strcmp, porporcionado una vez más por z88dk y una vez más de uso similar a la función homónima de la librería estándar de C de PC.
  • Si el comando introducido no se corresponde con ninguno de los que entienda el intérprete, se ejecutará la instrucción tras el else, mostrando por pantalla un mensaje de error para que el jugador sepa que el programa no le ha entenido.
  • Si el comando introducido es igual a m o mirar, lo que se hace es borrar la pantalla (escribiendo varios retornos de carro) y se llama a escribirDescripcion para que se muestre la información del a habitación actual. El método strcmp devuelve 0 si las dos cadenas pasadas como parámetro son iguales, y un valor distinto de cero en caso contrario.

Si compilamos el código y lo ejecutamos en el compilador, veremos que por fin ya podremos hacer algo con nuestro juego, aunque muy poco. Ya queda menos para que podamos movernos por nuestro mundo de aventura.

Por último explicaremos cómo hacer que el jugador pueda desplazarse por el mapeado de nuestra aventura conversacional. Deberemos hacer que nuestro intérprete de comandos entienda los comandos referentes al movimiento. Una forma de hacerlo es mediante el siguiente código:

while (final == 0)
{
    printf("Que hago ahora? - ");
    gets(comando);
    if (strcmp(comando,"m") == 0 || strcmp(comando,"mirar") == 0)
    {
        for (i=0;i<32;i++)
            printf("\n");
        escribirDescripcion(habitaciones,habitacion);
    }
    else if (strcmp(comando,"n") == 0 || strcmp(comando,"norte") == 0)
    {
        if (habitaciones[habitacion].direcciones[0] != 0)
        {
            habitacion = habitaciones[habitacion].direcciones[0] - 1;
            printf("\n\n");
            escribirDescripcion(habitaciones,habitacion);
        }
        else
            printf("\n\nNo puedo ir en esa direccion\n\n");
 
    }
    else if (strcmp(comando,"e") == 0 || strcmp(comando,"este") == 0)
    {
        if (habitaciones[habitacion].direcciones[1] != 0)
        {
            habitacion = habitaciones[habitacion].direcciones[1] - 1;
            printf("\n\n");
            escribirDescripcion(habitaciones,habitacion);
        }
        else
            printf("\n\nNo puedo ir en esa direccion\n\n");
    }
    else if (strcmp(comando,"s") == 0 || strcmp(comando,"sur") == 0)
    {
        if (habitaciones[habitacion].direcciones[2] != 0)
        {
            habitacion = habitaciones[habitacion].direcciones[2] - 1;
            printf("\n\n");
            escribirDescripcion(habitaciones,habitacion);
        }
        else
            printf("\n\nNo puedo ir en esa direccion\n\n");
    }
    else if (strcmp(comando,"o") == 0 || strcmp(comando,"oeste") == 0)
    {
        if (habitaciones[habitacion].direcciones[3] != 0)
        {
            habitacion = habitaciones[habitacion].direcciones[3] - 1;
            printf("\n\n");
                        escribirDescripcion(habitaciones,habitacion);
                }
                else
                       printf("\n\nNo puedo ir en esa direccion\n\n");
         }
         else
               printf("\n\nNo entiendo lo que dices\n\n");
    }
}

Lo único que se ha hecho ha sido introducir una sentencia if por cada comando que entiende el intérprete (después del else correspondiente al if anterior para evitar comparación con todos los comandos si ya se ha entenido qué es lo que el jugador quiere decir). Si el comando introducido por el jugador se corresponde con una dirección, se comprobará si se puede ir en esa dirección (examinando el valor de la posición adecuada en el array direcciones de la habitación actual), y en caso de que sea posible, se cambiará el valor de la variable habitacion (que marca la habitación en la que se encuentra el jugador actualmente) y se mostrará la descripción de dicha habitación. Si no es posible el movimiento en dicha dirección, se mostrará un mensaje adecuado.

Y ya está… si compilamos y ejecutamos el .tap en el emulador, veremos como ya podemos movernos por nuestro mundo conversacional.

Moviéndonos por el mundo que hemos creado

Hemos visto cómo utilizar un poco las funciones de entrada y salida y de cadenas de z88dk. Hemos comprobado que son iguales prácticamente a las del C estándar de los PCs actuales, excepto por la particularidad del formateo de texto visto al escribir las posibles direcciones por las que movernos (y alguna otra particularidad que todavía queda por describir).

A partir de ahora, crear la aventura conversacional será tan fácil como añadir nuevos comandos inteligibles por nuestro intérprete de comandos, mediante más sentencias if, y creando las estructuras de datos adecuadas para que eso sea posible. En próximas entregas crearemos objetos y haremos que el jugador pueda interactuar con ellos, al mismo tiempo que veremos algunas opciones más de formateo de texto.