Diseñando una aventura conversacional - Parte 5

Por Spellcaster

Traducido por DCG

¡¡En este capítulo nos meteremos de lleno en el alucinante y esencial mundo de los objetos!! Ninguna aventura conversacional sería realista al 100% sin 100000 objetos, pero para Fanglore seremos más modestos, y tan solo tendremos cuatro... Estos serán:

Puedes incluir otros objetos redundantes, sin propósito alguno, excepto el de confundir, o incluso divertir, al jugador... Pondremos en escena dos de estos objetos: Lo primero será, claro está, crear los objetos...

Creando objetos

Para crearlos, podemos utilizar el programa OBJGEN.PAS. Es muy parecido al ROOMGEN.PAS que venía con el SQ 1, excepto que en vez de crear localidades, crea objetos.

Bien, veamos qué es lo que necesitamos guardar para cada objeto: su nombre, su posición (podemos mover objetos de una localidad a otra o llevarlo en el inventario) y su descripción. Explicaré la parte de la descripción más adelante. Definiremos un record como este:

        Type TipoObj=Record
                         Nombre:String[80];
                         Pos:Byte;
                         Desc:Array[1..5] Of String[80];
                     End;
Definamos el número de objetos que habrán en el juego:
        Const NumeroObjs=6;
Y, finalmente, definamos el vector (array) que guardará los objetos:
        Var Objetos:Array[1..NumeroObjs] of TipoObj;
Esto, después de haber definido estas estructuras y haber obtenido el fichero OBJ.DAT (con el OBJGEN), tendremos todos los datos en el mismo, con lo cual sólo habrá que leer estos, con una rutina muy similar a LeerDatosLocalizaciones que ya vimos en nuestra segunda entrega:
        Procedure LeerDatosObjetos;
        { Leemos del disco los datos de los objetos }
        Var F:Text;
            A,B:Byte;
            Flag:Boolean;
        Begin
             { Preparamos el fichero de texto para el acceso }
             Assign(F,'Obj.Dat');
             Reset(F);
             { Para cada objeto del juego }
             For A:=1 To NumeroObjs Do
             Begin
                  { Leemos el nombre del objeto }
                  ReadLn(F,Objetos[A].Nombre);
                  { Leemos la posición inicial }
                  ReadLn(F,Objetos[A].Pos);
                  { Limpiamos la descripción del objeto }
                  For B:=1 To 5 Do Objetos[A].Desc[B]:='';
                  { Leemos la descrición }
                  Flag:=True;
                  B:=1;
                  While Flag Do
                  Begin
                       ReadLn(F,Objetos[A].Desc[B]);
                       If (B=5) Or (Objetos[A].Desc[B]='*') Then Flag:=False;
                       Inc(B);
                  End;
             End;
             Close(F);
        End;

Un apunte más... Si el campo POS de un objeto es 0, significará que estamos llevando el objeto, y si es 255, que el objeto está escondido (en el caso de la máscara de gas, ésta sólo aparece si el horno está abierto).

Contemplando los objetos

Un objeto es inútil, a menos que se pueda usar... Y sólo lo puedes usar si se ve, o si sabes que está allí... Así que hay dos clases de objetos que uno puede ver: objetos que llevas y objetos que ruedan por el escenario... Un buen juego tiene diferentes descripciones para cada una de estas dos clases, pero Fanglore se limita a tratarlos de la misma forma, soltando la descripción.

Bien, has de saber que hay un comando básico que es igual en TODAS las aventuras: ¡EXAMINAR!

Al comando examinar le sigue un parámetro, esto es, acepta (y requiere) que teclees otra cosa... Esta cosa es precisamente lo que deseas examinar... Por ejemplo, si quieres examinar la espada, uno teclearía:

EXAMINAR ESPADA

Examinar sería el comando, y la espada el parámetro. Pero date cuenta que uno no sólo puede examinar objetos, sino que puede examinar cualquier cosa del juego... Por ejemplo, el horno en la nevera... Hablaremos de esto en otro momento, en un próximo artículo de esta serie... Es importante decir que sólo puedes examinar objetos que o bien lleves o que estén en la misma localidad... Veamos como quedaría la rutina de EXAMINAR:

         Procedure Examinar(Param:String);
         Var Flag:Boolean;
             A,B:Byte;
         Begin
              Flag:=True;
              { ***************************************************** }
              { Aquí vendría el código para cosas como el horno, etc. }
              { ***************************************************** }
              { Buscamos el objeto en la lista de objetos }
              A:=0;
              Repeat
                   Inc(A);
                   If Objetos[A].Nombre=Param Then Flag:=True;
              Until Flag Or (A>NumeroObjs);
              If Flag Then
              Begin
                   { El objeto existe }
                   { Comprobamos que esté en localidad o bajo tu poder }
                   If (Objetos[A].Pos=0) Or (Objetos[A].Pos=LocalidadActual) Then
                   Begin
                        { El objeto es 'visible'... Sacamos descripción }
                        Writeln;
                        B:=1;
                        TextColor(Yellow);
                        While (B<6) And (Objetos[A].Desc[B]<>'*') Do
                        Begin
                             Writeln(Objetos[A].Desc[B]);
                             Inc(B);
                        End;
                        Writeln;
                   End
                   Else
                   Begin
                        { El objeto existe, pero no está visible }
                        Writeln;
                        TextColor(Yellow);
                        WriteLn('No veo el ',Param,' por aquí...');
                        WriteLn;
                   End;
              End
              Else
              Begin
                   { El parámetro especificado no representa ningún objeto  }
                   { existente...                                           }
                   WriteLn;
                   TextColor(Yellow);
                   WriteLn('Lo siento, pero no sé qué es un ',Param);
                   WriteLn;
              End;
         End;
Por supuesto tienes que completar la rutina que llama a esta procedure... Debes ponerlo todo (al igual que el resto de comandos) en Play. La rutina quedaría así:
        If Parsed[1]='EXAMINAR' Then
        Begin
                Valid:=True;
                Examinar(Parsed[2]);
        End;
¿Verdad que es fácil...? Pero aún no hemos acabado... Si te acuerdas de lo que dije a propósito del parseo, sabrás que las entradas se dividen en palabras... Pero resulta que la máscara de gas tiene 2 palabras como nombre (Gas Mask)... Tal como lo tenemos ahora el programa es incapaz de detectar los objetos con varias palabras. ¿Cómo podríamos arreglarlo? Bien, hay que volver a unir las palabras otra vez... Observa:
        If Parsed[1]='EXAMINAR' Then
        Begin
                Valid:=True;
                { Juntamos las palabras otra vez }
                D:=3;
                E:=Parsed[2];
                While Parsed[D]<>'' Do
                Begin
                        E:=E+' '+Parsed[D];
                        Inc(D);
                End;
                Examinar(E);
        End;
En cuanto a la definición de tipos, define E como string y D como un Byte. A pesar de que esto funciona con comandos de sólo un parametro, la cosa falla cuando hay comandos que requieren múltiples parametros... La regla es no utilizar objetos con nombres que llevan espacios...

Aún no hemos acabado la sección... Todavía nos queda ver que objetos hay en la localidad, y que objetos llevas... Pero esto lo dejaré para mañana, ya que ayer sólo dormí 2 horas... Y estoy MUY cansado...

Buenas noches... Zzzzzzzzzzzzzzzzzzzzzzzz..........

Ok... ¡He vuelto! :) Preparado para continuar... Ya... Nuestro problema es saber los objetos con los que podemos interactuar. Es fácil. Cuando entremos en una localidad, haremos que el programa saque una lista de los objetos visibles. Para conseguirlo, añadimos el siguiente código a la rutina de Mirar:

        TextColor(LightCyan);
        Writeln('Objetos visibles:');
        Flag:=False;
        For A:=1 To NumeroObjs Do If Objetos[A].Pos=NumeroLoc Then
        Begin
                Writeln('         ',Objects[A].Nombre);
                Flag:=True;
        End;
        If Flag=False Then Writeln('          Nada');
No olvides definir la variable Flag como un Boolean. Se usa para saber si hay algún objeto en la habitación... Si al salir del bucle For fuera falso, significará que no hay objetos en la localidad, y el programa notificará que no hay ningún objeto...

Para saber qué objetos estás llevando, usamos el segundo comando más conocido en las aventuras solo-texto... ¡El comando de INVENTARIO! Para implementarlo, sólo hace falta chequear todos los objetos del juego. Si su localización (campo POS) es cero, entonces es que lo estás llevando... Codificando:

        Procedure Inventario;
        Var A:Byte;
            Flag:Boolean;
        Begin
                Flag:=False;
                TextColor(LightBlue);
                WriteLn;
                WriteLn('Inventario:');
                For A:=1 To NumeroObjs Do If Objetos[A].Pos=0 Then
                Begin
                        WriteLn('                ',Objetos[A].Nombre);
                        Flag:=True;
                End;
                If Flag=False Then Writeln('                 Nada');
                WriteLn;
        End;
Como ya es habitual, debes añadir unas líneas a la rutina Play, para que llame a esta última:
        If Parsed[1]='INVENTARIO' Then
        Begin
                Valid:=True;
                Inventario;
        End;
Ahora ya podemos mirar los objetos... Pero nos queda la interacción, que dejaremos para el siguiente capítulo...


Nota de Spanish Quest: En los primeros números de 'The Mag' se realizó un cursillo de Pascal la mar de majo. Como comprenderéis no es cuestión de que lo reproduzcamos aquí, después de todo esto es una revista sobre aventuras, y no de programación. A los que no conozcáis Pascal y sepáis inglés os remito directamente a 'The Mag'. A los demás buscaos un buen tutorial en castellano, que seguro que los habrá perdidos en algún rincón de la red o miraros alguno de esos CD-ROMS que regalan las revistas, que puede que venga algún tutorial o cursillo interactivo de Pascal. Si el Pascal no os va, o simplemente conocéis algún otro lenguaje no os será nada complicado el pasarlo.


[Volver]