Páginas

29.6.18

Tutorial de juegos 'rpg' para Inform 7 - Acero (1) - Dados

Empecemos por lo más evidente. Si quieres un sistema 'rolero' vamos necesitar tiradas, dados, alguna clase de aleatoriedad. Inform 7 tiene un montón de mecanismos de aleatoriedad disponibles como podéis ver en este capítulo del manual y en otras secciones como las referentes a listas o tablas, así que en realidad no necesitaríamos desarrollar nada, pero la verdad es que la mayor parte de los sistemas expresan sus tiradas en forma de combinaciones de dados más o menos complejas y si incluimos una notación común para expresar 'tiradas' nos resultará mucho más sencillo luego incluir tablas con toda clase de conceptos que constituyan el sistema sobre el que se soporte la historia. Por otra parte es un buen momento para aprender cómo se hace y se incluye una extensión, así que hagamos una extensión de dados y sus tiradas.

La mayor parte de los sistemas usa dados poliédricos numerados, aunque algunos usan cosas más extrañas (es un clásico mencionar que el juego de rol del Príncipe Valiente usa sólo monedas para las tiradas), y expresan la tirada en la forma de xdy+z ó xdy-z, que significa tira 'x' dados de 'y' caras y suma (o resta) 'z' al total. Otra tirada muy habitual es la de 1d100 o d%, que es una tirada entre 00 y 99 ó 01 y 100, según sea el sistema; que habitualmente se consigue tirando dos dados de diez caras y leyendo de forma consecutiva (una junto a la otra) el valor de cada dado. 

Podemos crear una nueva extensión desde el propio IDE (File >> New Extension), lo que genera una estructura completamente vacía como esta:


Rolling Dices by Johan Paz begins here.

Rolling Dices ends here.

Lo mínimo que deberíamos incluir en cualquier extensión es la documentación de la misma de esta forma:

Rolling Dices by Johan Paz begins here.

"This extension allows express set of dices as a value and rolling them"

Rolling Dices ends here.

---- DOCUMENTATION ---- 

This extension allows express set of dices as a value and rolling them.

En la parte de la documentación explicaremos la extensión y pondremos al menos un ejemplo de uso. Estos ejemplos son muy útiles porque se pueden cargar como proyecto nuevo y así probar directamente la extensión tal y como la haya creado su autor. Si construis una extensión no dudéis en contarlo por aquí o aquí y, si es realmente útil, os explicaremos como publicarla, adaptarla, etc...

Inform 7 tiene una forma de incluir notaciones de unidades con más de una parte, y es bastante general, así que podríamos usarla para incluir el formato de dados, de esta forma:

A roll is a kind of value. 99d99+99 specifies a roll with parts dices, sides and pluses (optional, preamble optional).

Ahora podríamos incluir el 'lanzado' de dados de esta forma:

To decide which number is the throw of (dices - a roll):
 let numPart be the dices part of dices;
 let sidePart be the sides part of dices;
 let randomPart be 0;
 repeat with index running from 1 to numPart:
  increase randomPart by a random number from 1 to sidePart;
 increase randomPart by the pluses part of dices;
 decide on randomPart.

Si añadimos una excepción para el d% ya tendríamos casi todo lo relativo a tiradas que vamos a necesitar:

To decide which number is the roll of d%:
      decide on a random number from 1 to 100.

Añadiendo un ejemplo de prueba como este:

"Dices" by Johan Paz

Include Rolling Dices by Johan Paz.

Rolling site is a room.

A dice (m) is a kind of thing. A dice has a roll called dice roll.

A four sided dice is a dice in rolling site. The dice roll of four sided dice is 1d4.
A six sided dice is a dice  in rolling site. The dice roll of six sided dice is 1d6.
A eight sided dice is a dice  in rolling site. The dice roll of eight sided dice is 1d8.

Dice rolling is an action applying to nothing.

Understand "roll dices" as dice rolling.

Carry out dice rolling:
 let total be 0;
 repeat with dice running through dices carried by player:
  let result be roll of dice roll of dice;
  say "You roll the [dice]... obtaining [result].";
  increase total by result;
 say "The total is [total].".
 
Test me with "take four sided dice / roll dices / take six sided dice / roll dices / drop all / take all / roll dices".

ya tendríamos nuestra primera extensión lista para ser usada. La podéis ver completa aquí.

27.6.18

Tutorial de juegos 'rpg' para Inform 7 - Acero (0)

A lo largo de los años he visto y escuchado hablar a mucha gente de hacer una ficción interactiva con 'elementos roleros', o decir que le gustaría hacer un 'rpg' o algo parecido. Y no sólo eso, sino les he visto buscar herramientas o librerías 'de rol'. A este respecto he decir que cuando se habla de esto no me parece que se esté hablando realmente de 'juegos de rol', sino de 'crpg'. La realidad es que cuando se habla de 'incluir elementos roleros' en una ficción interactiva se está pensando en cosas como que haya combates, que los personajes tengan habilidades, puntos de vida, etc... es decir, la parte de los juegos de rol menos interesante, el sistema de juego.

Las mejores sesiones de rol de mesa son aquellas en las que ni se sacan las fichas de personaje porque no es necesario, en las que no se tira ni un dado ni se mira ningún número. Las mejores sesiones de rol de mesa tienen interpretación, descripciones y muchos diálogos. Sí, como alguno estará pensando, las mejores sesiones de rol de mesa son ficciones interactivas sin 'elementos roleros' y donde el parser es un humano. Las sesiones en las que se usa masivamente el sistema de juego son habitualmente largas tardes de combate que a mí, normalmente, me aburren. Evidentemente de tanto en tanto se hacen y hay que hacerlas, porque a veces no queda otra que resolver las cosas por la fuerza de las armas, pero al final es un repetitivo uso de dados y listas de poco interés.

El otro 'aspecto rolero' que suele despertar interés es el 'coleccionismo de objetos', aquello de 'oh, wow, tengo una espada +3 con Protect The Innocent encantado'. De nuevo esto sólo es tangencialmente 'rolero' de hecho nosotros al montón de objetos 'mágicos' que llevan los personajes lo llamamos en las partidas 'quincalla' y decimos cosas como 'uff... esto lo hemos resuelto gracias a la quincalla, tenemos que pensarlo mejor la próxima vez'. El coleccionismo de objetos alcanza verdaderamente su clímax en los que han dado en llamar 'arpg'. De hecho no le veo ningún interés a jugar a un 'arpg' si no es por la montaña de objetos 'especiales' que se sacan de ir despanzurrando 'enemigos' con repetidos clicks del ratón.

Así que antes de incluir 'elementos roleros' en tu ficción interactiva lo primero que te debo decir es que te pienses bien si realmente los necesitas. La parte 'chula' del rol ya está en cualquier ficción interactiva, y lo que vas a incluir es en realidad accesorio y más un inconveniente a la narrativa que una ventaja. Asegúrate de saber bien lo que estás haciendo y ten en cuenta las diferencias que existen entre el medio que es la FI con el que puede ser un 'rogue', un 'crpg' o un 'arpg'. Si intentas duplicar un 'arpg', por ejemplo, en texto te va a quedar bastante soso, porque probablemente en un 'arpg' la parte visual y sonora es parte fundamental de la experiencia.

Si estás seguro de que quieres incluir 'elementos roleros' el siguiente problema que vamos a encontrarnos es de qué sistema queremos partir. Hay muchos y no se parecen demasiado. No tiene mucho que ver incluir reglas inspiradas en BRP, en d20, en D6, en Rolemaster, en GURPS... En realidad, si creamos una librería 'rolera' inspirada en d20 habrá cosas que recordarán a D&D de forma parecida a cómo la experiencia de los juegos de Elder Scroll a mí me recuerda a los juegos de Rolemaster. Y, encima, no es tan fácil crear un módulo para una de esos sistemas, tienen que haberlos usado bastante para hacerte una idea de qué va a funcionar y ser interesante en cada uno de ellos. Yo me atrevería a hacer módulos de BRP, d20 y, tal vez, D6, pero ni de lejos me atrevería a escribir un módulo de otro de esos sistemas, al menos no un módulo que no sea minúsculo. Vamos, ni se me pasaría por la cabeza intentar escribir un módulo para 'Vampiro: La Mascarada', por poner un ejemplo.

Una buena posibilidad sería que sabiendo la historia que vayas a contar buscaras la campaña de rol que más te recordara a tu historia y te empapes del sistema de juego que se ha usado normalmente para los módulos de dicha campaña. Es decir, si vas a contar una historia basada en Star Wars u otro space opera, probablemente sea buena idea basarte en D6, si es un rollo alta fantasía tira por d20 y si es algo de fantasía más adulta y sucia prueba con BRP.

Dicho esto en los próximos capítulos de este tutorial os daré ejemplos de cómo hacer diversas cosas 'roleras' y lo haremos en el marco de una obra a la que llamaré 'Acero'. Para los ejemplos usaré el sistema que llevamos años usando en mi grupo de rol al que llamamos S3 y que surgió a partir de BRP.

26.6.18

Tutorial de creación de ficción interactiva - Huesos (y 15)


Busquemos ya la salida de este tutorial, que hemos pasado ya mucho tiempo en la oscuras tierras de huesos y reglas. En el anterior capítulo ya habíamos conseguido que nuestro minimundo tumulario fuese bastante coherente y contuviese todos los elementos necesarios para nuestra historia. Veamos que retoques necesita para que contenga también nuestra historia y no sólo una extraña simulación de la edad del bronce.

Lo primero es que la protagonista no debería encontrarse con el fin de la historia demasiado pronto, esto ya lo habíamos hecho en el caso de Squiffy, aquí lo podemos hacer simplemente añadiendo alguna regla más de 'Do the player mean':

Definition: a tinaja is sacred if restos de un sacerdote is in it.
Does the player mean opening a sacred tinaja 
  when there are less than three open tinajas: it is very unlikely.

Lo he hecho en dos pasos para que veáis cómo es posible mezclar diversos mecanismos de control. Por una parte defino que una tinaja sagrada si contiene un sacerdote (el único que contiene el mundo del juego en este caso) y luego uso esa definición junto con el requisito de que haya menos de tres tinajas abiertas para decirle al parser que mejor no considere la tinaja del sacerdote si es demasiado pronto. Creo que queda bastante elegante, ¿no os parece?

Vale, y cuando aparece el sacerdote, ¿qué? Pues en la versión de Squiffy desarrollábamos el temor de la protagonista y finalmente cuando intentaba vaciar la tinaja cambiábamos el escenario apagando la luz y haciendo que huyese. Primero revisemos la descripción de los restos del sacerdote y metamos algo de los textos de Squiffy usando la técnica de los examina en diversos intentos:

Chapter 8 - Historia

Section 1 - Examina

Does the player mean examining restos sacerdote when the restos de sacerdote is in a open tinaja: it is very likely.

Instead of examining restos de sacerdote for the first time:
 say "Los restos del sacerdote parecen demasiado bien conservados. Su piel está seca, como costra salada, 
             pero aún tiene cara. Una cara de sonrisa excesiva y amenazadora que  te ha hecho soltar un breve 
             grito al destapar la tinaja.".
 
Instead of examining restos de sacerdote for the second time:
 say "No entiendes cómo un sacerdote puede estar aquí en el túmulo del pueblo. No tiene sentido.  
             Los sacerdotes ya no se entierran en el pueblo. Viven apartados, en su propia colina y por 
             lo que sabes los entierran allí mismo, en los cimientos del templo dedicado a Potnia. Pero 
             éste está aquí, y está casi entero, casi sin corromper. ¿Por qué está en el túmulo tan lejos 
             del resto de los suyos?".

Instead of examining restos de sacerdote for the third time:
 say "Potnia, la diosa de los animales es adorada, por todo el que tiene juicio, pues de ella 
             depende toda prosperidad, así como la suerte en los partos o que las tormentas y las heladas 
             no destruyan las cosechas. Hasta la luz nace de ella, al menos si está de humor. Mover los 
             restos de uno de sus sacerdotes podría ser un gran pecado, por ello te tiemblan las manos 
             al pensar en sacar al sacerdote de su tinaja.".
 
Instead of examining restos de sacerdote:
 say "Cuánto más lo miras más segura estás de que debes salvaguardar estos restos y  también que 
             si lo haces atraerás contra ti y tus descendientes las peores maldiciones de Potnia. Tal 
             vez vuestros ganados perezcan y vuestras mujeres se vuelvan estériles.".

Buen truco lo de 'for the X time', ¿eh? Inform 7 os da siempre muchas herramientas para hacer las cosas como estáis viendo, aunque a veces eso ha jugado en su contra, así que si os perdéis y qué es mejor (probablemente todas las formas sean válidas) ya sabéis que podéis preguntar lo que queráis aquí y aquí. Y, de nuevo, podéis ver cómo las reglas más 'concretas' siempre se considerarán antes en I7 frente a las más generales.

Vale, ahora habrá que proporcionar una reacción adecuada al verbo 'tocar', ¿no? Porque en estos textos se mencionan un buen montón de texturas, se habla de sequedad, etc... Inform ya trae 'touching' como acción, así que nos bastará con darle contenido para algunas cosas que nos parezcan relevantes, por ejemplo:

Section 2 - Tocar
 
Instead of touching a tinaja:
 say "Rugosa, vieja, segura.".
 
Instead of touching a contenido:
 say "Secos, conocidos. Nunca los manipularías sin el debido respeto.".
 
Instead of touching a piedra de chispa:
 say "Con bordes afilados, pero no cortantes.".
 
Instead of touching a saco:
 say "Burdo, basto, lo bastante apretado para contener los restos de vuestros antepasados.".
 
Instead of touching restos de un sacerdote:
 say "Seco y quebradizo. El tacto del sacerdote te pensar en maldiciones, en enfermedades, en ovejas 
             estériles y cabras de ubres secas, en todo lo negativo que la diosa Potnia podía llegar a 
             desatar contra los que no respetan las tradiciones.".

Y ahora al meollo, qué pasa si intentas coger los restos del sacerdote o vaciar su tinaja (añadiendo un pequeño sinónimo además):

Instead of taking a contenido when the noun is in a tinaja (called vase):
 try emptying vase.

Section 3 - Vaciar tinaja del sacerdote
 
Instead of emptying a sacred tinaja for the first time:
 say "Con muchísimo cuidado y aún más respeto haces un intento de tirar de los flacos 
             y secos brazos del sacerdote, pero la piel está quebradiza y frágil.";
 say line break;
 say "Al primer sonido de desgarro te da un vuelco el corazón.";
 say line break;
 say "No vas a poder hacerlo. No vas a poder. Si tiras más del sacerdote lo vas
              desmembrar. Aunque debes.".

Instead of emptying a sacred tinaja:
 say "Vuelves a intentarlo, pero tanto es el miedo que tienes que caeshacia atrás.";
 say line break;
 say "Con horror ves como la lámpara rueda por el suelo hasta apagarse.";
 now the lampara is not lit;
 move the lampara to the tumulo.

Ya hemos provocado que con su segundo intento la protagonista se quede a oscuras y sin lámpara, lo que en realidad hace que no pueda hacer nada de nada, excepto lo que le permitamos, como por ejemplo:

Section 4 - Salir o moverse en la oscuridad

Instead of exiting when in darkness and there is a sacred open tinaja for the first time:
 say "Intentas encontrar el camino de salida, pero sólo logras tropezar con alguna tinaja volcándola y 
              haciéndote daño en las rodillas.".
 
Instead of exiting when in darkness and there is a sacred open tinaja for the second time:
 say "Vagas por entre las tinajas con más cuidado, intentando aguzar tu envejecida vista buscando 
             el escaso resplandor del pasillo de entrada. Pero no logras ver nada.".
 
Instead of exiting when in darkness and there is a sacred open tinaja for the third time:
 say "Te parece escuchar los pasos tambaleantes de la momia del sacerdote que te busca en la 
            oscuridad mientras te abres paso apresuradamente entre las tinajas para darte de bruces contra una pared.".
 
Instead of exiting when in darkness and there is a sacred open tinaja for the fourth time:
 say "Con la respiración ya muy alterada y sin saber muy bien como sales al exterior.";
 secuencia final.
 
Instead of exiting when in darkness:
 say "No tiene sentido marcharse hasta no haber recogido los restos de tus antepasados.".

Ya tenemos la secuencia final usando 'salir' como comando clave, excepto que falta eso de 'secuencia final'. Inform 7 permite agrupar varias cosas dentro de una frase nueva de esta forma:

To secuencia final:
 say line break;
 say "...";
 wait for any key;
 end the story saying "Mientras la anciana corre asustada desde el túmulo hacia su aldea, 
         en la oscuridad el sacerdote, que no se había movido de la tinaja, sonríe. No había tenido 
         que hacer casi nada, tan sólo apagar una lámpara- y no tendría que pagar un precio demasiado 
         alto por trastear entre los vivos en aquella ocasión. Sabía que ella ya no regresaría y que 
         para cuando llegasen los hombres de Esus -demasiado pronto ya- ella, la anciana piadosa, 
         estaría lejos y a salvo.".

Pues ya tenemos vuestra primera aventura... más o menos. Faltaría añadir una intro de forma parecida a como hemos puesto una secuencia final, por ejemplo:

Section 5 - Secuencia inicial

When play begins:
 say "Lo más impresionante es el silencio. Lo más terrorífico la oscuridad. 
          En el mundo de los vivos el sonido lo permea todo. Los ruidos son constantes. 
          Los trinos de los pájaros. Las llamadas de las cigarras. Los berridos del ganado. 
          Las voces de la gente. La vida es ruidosa. Hasta los espírtus más cotidianos como 
          el arroyo y el viento se anuncian con el sonido.";
 say line break;
 wait for any key;
 say "Sin embargo los muertos viven en el silencio frío y oscuro del túmulo. No es 
          un lugar para los vivos, ni lo es para ti, una anciana.";
 say line break;
 wait for any key;
 say "Los antepasados crearon el túmulo con enormes paredes de piedra, tan gruesas 
          que parece casi inexplicable ahora que pudiesen moverlas sin ser héroes gigantes 
          y míticos. Tal vez lo fuesen, pero sabes que nada quedaba fuera del alcance de una 
          pueblo unido y decidido. Nadie sabe ya si crearon estas fuertes paredes para proteger 
          a los muertos de los saqueos o a los vivos de que los muertos regresasen, pero fuese por 
          lo que fuese lo que queda fuera del túmulo era el sonido de la vida.";
 say line break;
 wait for any key;
 say "El túmulo es un mundo ajeno, pero has tenido que venir a salvar los restos de vuestros 
          antepasados de los hombre gigantes de Esus.";
 clear the screen.

Y ya está. Más o menos, realidad queda mucho que se mejorar y ampliar, pero, ¿por qué no lo hacéis vosotros? Hacedla mejor, más detallada, más completa y si queréis mostradnos vuestra versión aquí.

Aquí acaba este tutorial y el resultado final podéis descargarlo aquí o ver el resultado compilado aquí.

También podéis verlo en itchio aquí.

25.6.18

Tutorial de creación de ficción interactiva - Huesos (14)

En el último capítulo dejamos pendiente reconsiderar si la política de elección de objetos para el comando de examinar era el más adecuado. Lo que realmente queremos conseguir es que una secuencia como: abrir tinaja, examina tinaja,  vaciar tinaja, abrir tinaja, vaciar tinaja... tenga unas respuestas adecuadas, y la actual lo hace de forma no muy fina. Parece que necesitamos de alguna forma saber cuál es la última tinaja que la protagonista haya abierto y tenerlo en cuenta para tener una experiencia de interacción coherente e intuitiva.

Hay varias formas de anotar cuál es la tinaja que ha sido la última abierta. Vamos a usar la que menos le gusta a un programador, la variable global y de paso aprendemos cómo usarla:

The last open tinaja is an object that varies. 

Hago que sea 'object' y no 'tinaja' para que su valor inicial sea 'nada', lo que nos permite verificar si hemos abierto alguna tinaja antes. Otras formas de hacer esto sería:

  1. Poner una marca de 'última abierta' en las tinajas, pero entonces tendríamos que activar y desactivar esta marca manualmente, así como tendríamos que crear todo lo necesario para localizar cuál es la última, etc...
  2. Poner un marcador en cada tinaja con el 'turno' de cuándo las abrimos, véase esta parte del manual de Inform, para entender el tratamiento del tiempo en esta herramienta. Esta aproximación al menos no requiere que se active y desactive la marca, pero sigue requiriendo crear lo necesario para localizar cuál es la última tinaja que se abrió.
En este caso nos sobra con la variable global, pero tened cuidado con ellas, si usáis muchas podéis acabar teniendo un montón de referencias cruzadas y comportamientos inesperados. Usadlas con mucha precaución. Nuestra variable global se actualizaría con la siguiente modificación:

After opening tinaja:
 if there is a contenido (called content) in the noun:
  say the description of the content;
  say paragraph break;
  now the last open tinaja is the noun;
 otherwise:
  say "Esta tinaja ya no contiene más que polvo.".

Y una vez que sabemos cuál es la última tinaja que hemos abierto podemos modificar el comando examinar para que tienda a apuntar a ella de esta forma:

Does the player mean examining a thing which is examined: it is very unlikely.
Does the player mean examining a tinaja which is the last open tinaja: it is very likely.

Si lo probáis veréis que no está mal, pero los 'contenidos' necesitan algunos retoques para verse bien, por ejemplo en la lista del inventario. Lo que he hecho es renombrarlos en la tabla y cambiar su artículo indeterminado de esta forma:

The indefinite article of a contenido is usually "los".

Table of Contenidos Tinajas
contenido description
a restos de Belaiska "El olor es aún intenso dentro de la tinaja pero el cuerpo 
ya sólo era un pequeño montón de huesos.  
Esta es la tinaja donde enterrásteis a Belaiska, la mujer de tu hermano, muerta de parto."
...

De esta forma si el parser intenta pintar el nombre del contenido de Belaiska mostrará 'los restos de Belaiska' lo que está bastante bien. Ahora empecemos a guiar un poco al interlector en su misión de recoger los huesos y digámosle que no ande abriendo tinajas ni ton ni son:

Before opening tinaja:
 if the noun is not the last open tinaja and there is a contenido in the last open tinaja:
  say "Mejor no abramos más tinajas hasta que recuperemos los restos de las que ya tenemos abiertas.";
  stop the action.

Es un poco más restrictivo de lo que me gusta pero para esta obra tiene bastante sentido. Ahora que le hemos limitado a abrir una tinaja cada vez tendremos que darle la posibilidad de usar el saco. Creemos para empezar la acción de 'vaciar':

Chapter 7 - Vaciar

Emptying is an action applying to one thing.

Understand "vacia [something]" as emptying.

Carry out emptying:
 say "No parece algo que pueda vaciarse.".

Y ahora construyamos la acción de vaciar tinaja concretamente:

Does the player mean emptying a tinaja which is the last open tinaja: it is very likely.
 
Instead of emptying an open tinaja when there is a contenido (called content) in the noun:
 say "Recoges con cuidado los [the printed name of content] y los guardas en tu saco.";
 move the content to saco.

Véase que sólo hemos creado una reacción diferente cuando estamos refiriéndonos a una tinaja que tiene un contenido, si está vacía irá por el comportamiento general. Esta es la forma más adecuado en Inform 7, no os pongáis a meter condicionales dentro del cuerpo de la regla si podéis ponerlas en la declaración de la misma, de esta forma funcionarán conjuntamente de mucho más armoniosamente. Daos cuenta también cómo hemos usado la información de cuál es la última tinaja abierta para recomendar al parser que use esa para la acción de vaciar.

¿Podría referirse el interlector a una tinaja concreta por ejemplo refiriéndose a su contenido? Pues sí, la verdad, ya que Inform 7 permite referirse a cualquier objeto de varias formas como por su nombre/adjetivos, pero también por sus propiedades y sus relaciones (véase este capítulo); y no sólo eso, nos proporciona una serie de relaciones preconstruidas y con ellas es posible escribir:

Understand "tinaja de [something related by containment]" as a tinaja when the item described is open. 

Rule for printing a parser error when the latest parser error is the can't see any such thing error :
 if the player's command includes "tinaja": 
  say "¿Qué tinaja es esa?";
 otherwise:
  say "No sé a qué te refieres.".

Si probamos el estado actual de esta obra, ¡wow!, ya tenemos todo lo necesario para que el interlector pueda interactuar con el minimundo que le hemos creado y haga todo lo que esperamos que haga. ¿Qué nos falta entonces? Pues en realidad nos falta la historia. El interlector debe poder ir abriendo tinajas -lo tenemos-, guardando huesos -lo tenemos- hasta que se encuentre con los restos del sacerdote y se 'desencadene' el drama. La historia, como vamos a ver, está constituida por una serie de reglas concretas que modifican el comportamiento general del mundo que hemos creado para darle sentido a la obra. Pero esto lo veremos en la siguiente y, probablemente última, entrega de este tutorial.

14.6.18

Tutorial de creación de ficción interactiva - Huesos (13)

Si probáis a abrir una tinaja veréis dos cosas: primero que el texto de respuesta es bastante inadecuado, porque no te dice nada de lo que encuentras y además podréis comprobar que si intentas repetidamente 'abrir tinaja' va a intentar abrir la misma tinaja una y otra vez. El comportamiento no se parece en nada al que obtuvimos en la versión Squiffy, ni tampoco a la idea del 'flujo de acción' del relato original (una anciana que va abriendo tinajas y vaciando el contenido con respeto y cuidado en un saco). Necesitamos que la secuencia sea algo parecido a: 'abrir tinaja', 'examinar tinaja', 'vaciar tinaja', 'abrir tinaja', 'vaciar tinaja'... Dado que no hemos 'nombrado' (ni queremos) cada una de las tinajas, podría parecer todo un reto crear un mecanismo de interacción que resulte fácil y al mismo tiempo intuitivo para el interlector; pero no lo es. Sé que alguno estará pensando, "pero, pero... ¿no tenemos que nombrar cada tinaja de una forma diferente para que el interlector pueda decir vacía esa tinaja y luego aquella otra?".

:)

Pues la verdad es que no. La solución tradicional a este problema en un 'juego de aventuras' sería pintar cada tinaja de un color, o hacer que cada tinaja sea de una arcilla diferente, o decir que unas están descascarilladas mientras que otras están agrietadas. A fin de cuentas hay hasta una obra inglesa que usa tal solución como puzle: 69105 keys. En esta obra hay literalmente 69105 llaves pero sólo hay un formato de llave que sólo tiene una copia, ¡encuéntrala si puedes!. En el fondo esta obra lo que contiene es un 'meta puzle', es algo que tiene sentido por el medio que se usa y por la forma en la que se resuelve 'habitualmente' la ambigüedad. Para abrir la puerta de la obra tendrás que escribir algo tan chungo como 'abre la puerta con la llave pequeña de hierro con mango azulado, cabeza ovalada y diente cuadrado'. 

:)

Salvaje. Como puzle. Pero, ¿no sería posible resolver el puzle escribiendo 'simplemente': > probar con una llave, probar con una llave, probar con una llave, probar con una llave.... [69101 veces más]?  Y la obra debería responder con:

> probar con una llave. probar con una llave...
Pruebas con la llave pequeña de hierro con mango azulado, cabeza ovalada y dientes cuadrados. No funciona.
Pruebas con la llave pequeña de hierro con mango azulado, cabeza ovalada y dientes triangularas. No funciona.
Pruebas con la llave pequeña de hierro con mango azulado, cabeza ovalada y dientes redondeados. No funciona.
Pruebas con la llave pequeña de hierro con mango azulado, cabeza rectangular y dientes cuadrados. No funciona.
....
¡Vaya la llave mediana de hueso de dragón con mango dorado, cabeza triangular y dientes redondeados sí que logra abrir la puerta!

Como solución a ese puzle pierde toda la gracia, pero para nuestra obra sí que tendría sentido. Y diría más, para gran parte de las obras de ficción interactiva la distinción usando adjetivos diferenciados es un auténtico dolor para el interlector que tiene que teclear una y otra vez los 'adjetivos' que identifican al objeto concreto con el que quiere interactuar y, sin embargo, la usamos una y otra vez. Va siendo hora que nos liberemos de ella, veamos cómo.

Lo primero es cambiar el mensaje estándar que devolvemos al abrir una tinaja, esto se logra mediante las reglas 'After' de esta forma:

Chapter 5 - Abrir tinaja

After opening tinaja :
 if there is a contenido (called content) in the noun:
  say the description of the content;
  say paragraph break;
 otherwise:
  say "Esta tinaja ya no contiene más que polvo.".

Podéis ver que hemos incluido una respuesta útil para las tinajas que no contengan nada. Esto nos permite subir el número de tinajas por encima del número de contenidos, como a 12 por ejemplo -no nos pasemos o el interlector pensará que se han acabado las tinajas que vaciar y que el resto está vacía. Como ya sabéis para lograr esto basta con subir el número de tinajas y de tapas.

There are twelve tapas.
There are twelve tinajas.

Si probáis la obra ahora veréis, que 'abrir tinaja' insiste en usar una y otra vez la misma tinaja, ¿cómo resolvemos esto? Pues es brutalmente sencillo, incluyamos es única línea extra de código.

Does the player mean opening a tinaja which is open: it is very unlikely.

Ahora le hemos explicado al parser que es muy poco probable que el interlector quiera abrir una tinaja que ya está abierta. Probadlo. Magia negra, ¿eh? Inform 7 tiene cosas realmente maravillosas en su interior. Podemos hacer lo mismo a la hora de examinar tinajas, para que 'ex tinaja' no nos de el mismo resultado una y otra vez.

Chapter 6 - Examinar tinaja

A tinaja can be examined. A tinaja is usually not examined.

Does the player mean examining a tinaja which is examined: it is very unlikely.

After examining or opening a tinaja:
 now the noun is examined.

Fijaos lo fácil que resulta añadir una cualidad nueva a cualquier objeto o clase de objeto, darle un valor inicial y hacer que dicha cualidad cambie tras una acción o varias. Daos cuenta que podría haber puesto el cambio de la propiedad en la anterior sección, ya que ahí hemos definido lo que pasa 'después de abrir una tinaja', pero me ha parecido más fácil de entender si lo ponía aquí y funciona. Inform 7 os permite añadir el código cerca de la sección que determina un comportamiento, y eso en obras grandes es realmente útil. Por supuesto podemos hacer lo mismo con las tapas, de esta forma:

Chapter 7 - Examinar tapa

A tapa can be examined. A tapa is usually not examined.

Does the player mean examining a tapa which is examined: it is very unlikely.

After examining or opening a tapa:
 now the noun is examined.

¡Pero es el mismo código! Mejor hacerlo de forma algo más general:

Chapter 6 - Examinar rotativo

A thing can be examined. A thing is usually not examined.

Does the player mean examining a thing which is examined: it is very unlikely.

After examining or opening a thing:
 now the noun is examined.

Mucho mejor. En Inform 7 si veis la forma de hacer algo de forma general, hacedla de forma general, e incluso os diría que si no veis como hacerlo de forma general pasaos por textualiza o por el caad y preguntadnos. Muy pocas veces implementar el caso concreto en lugar del general sale rentable, y el caso general os dará un rico y, a veces, agradablemente sorprendente resultado cuando interactuéis con la obra por hilos raros de la historia.

Pero seamos un poco críticos. ¿Queremos realmente este comportamiento en el caso de examinar? Está genial para ir examinando tinajas cerradas y ver un poco todo lo que hay, pero si el interlector está haciendo de la anciana que acaba de abrir una tinaja concreta, ¿el comando examina no debería referirse a esa tinaja? Desde luego el comando vaciar debería hacerlo. ¿O tal vez deberíamos tener un comportamiento diferente con las tinajas abiertas o cerradas? ¿O es que deberíamos distinguir entre la propia tinaja abierta y su contenido? Uff... habrá que escoger y no es una elección obvia. Al final tendréis que escoger en vuestras obras una interacción que os parezca la más lógica e intuitiva para el interlector, y eso no es algo que sea independiente de la obra misma.

En la próxima entrega os explicaré cuál ha sido mi decisión a ese respecto y cómo lo he implementado. ¡Por cierto nos olvidamos en la anterior entrega que la anciana también lleva un saco! ¿Sabríais incluirlo? Venga incluidlo vosotros mismos y si no siempre podéis mirar cómo lo he dejado yo aquí.

13.6.18

Tutorial de creación de ficción interactiva - Huesos (12)

Vamos a redondear algunas cosillas básicas antes de meternos con lo que queda de narrativa principal -nos queda el bucle de ir abriendo vasijas hasta que encontramos al sacerdote, apagamos la linterna que se cae en la oscuridad, miedo, etc...

Ya teníamos una lámpara, un entorno oscuro y ya se podía encender y apagar la lámpara, pero la verdad es que lo hemos simulado todo de una forma muy superficial. Para encender fuego es necesario un yesquero que normalmente está compuesto por algo 'metálico', un pedernal que produce chispas al chocarlo con el metal y algo de yesca o que prenda con facilidad. Todo eso estaba en el relato original y en la versión de Squiffy, así que deberíamos incluirlo en el inventario inicial de la protagonista. No es muy difícil ver como sería:

Section 5 - Objetos para encender la lámpara

A piedra de chispa (f) is a thing carried by the player.
The description of piedra chispa is "Gris oscura con vetas casi blancas. De bordes duros, cortantes, 
fácil de afilar. Los hombres del sur las usaban para crear sus armas en tiempos remotos. Es la que 
crea el fuego cuando se la golpea contra la piedra del sol, como si la piedra del sol le prestase 
el calor.".

A piedra de sol (f) is a thing carried by the player.
The description of piedra sol is "Dorada sin ser oro.  Dicen que cayeron del sol en el lejano norte.".

A yesca (f) is a thing carried by the player.  The indefinite article of yesca is "algo de".
Understand "algo de yesca" or "poco de" as yesca.
The description of yesca is "Hilos de sus mejores vestidos viejos, mezclado con hongo de árbol seco. 
Recibe la semilla del fuego y crea la llama.".

Algo interesante que podemos ver en se código es cómo tratar incontables (algo de yesca, un montón de harina, un poco de agua...). La parte importante es que es muy incorrecto que se refieran a ellos como 'un/una' algo al describirlo, por eso le decimos al compilador que su artículo indefinido es otro diferente: "algo de".

Con esos tres objetos creados ya podemos enriquecer la regla del encendido requiriendo los tres objetos para poder encender la lámpara. Una primera aproximación sería:

Instead of switching on the lampara when lampara is carried and piedra de chispa is carried 
      and piedra de sol is carried and yesca is carried:
 say "Con dificultad tus viejos dedos entre chocan las dos piedras para hacer una pequeña 
             llama en la yesca con la que  enciendes la lámpara.";
 now the lampara is lit.
 
Instead of switching on the lampara:
 say "Necesitas la piedra de sol y la piedra de chispa, así como algo de yesca para enceder 
             la lámpara.";
 stop the action.

Aquí podemos ver en funcionamiento la magia de las reglas que se ejecutan según orden de 'especificidad'. La primera regla requiere que se cumpla una condición así que se ejecutará primero, la segunda, sin embargo, se considerará después. Si lo probáis veréis que funciona estupendamente y en esta clase de cosas está la magia y dificultad de I7. El que las reglas tengan prioridad según como de concretas sean es lo que nos permite separar nuestro código en pequeños fragmentos manejables, distribuidos incluso entre extensiones y que todo funcione.

Pero la verdad es que nuestra aproximación es un poco horrible con todos esos 'and' tras el 'when', habría que organizar esto un poco mejor. Para empezar encapsulemos esas condiciones en una sola de esta forma:

To decide if the player can lit a fire:
 if piedra de chispa is carried and piedra de sol is carried and yesca is carried:
  yes;
 otherwise:
  no.

Instead of switching on the lampara when the player can lit a fire and lampara is carried:
 say "Con dificultad tus viejos dedos entre chocan las dos piedras para hacer una 
             pequeña llama en la yesca con la que  enciendes la lámpara.";
 now the lampara is lit.

Con lo que hemos aprendido como 'definir nuevas condiciones' en I7 usando 'To decide if'. Este procedimiento permite utilizar parámetros de esta forma:

To decide if (actor - a person) can lit a fire:
 if piedra de chispa is carried by actor and piedra de sol is carried by actor and yesca is carried by actor:
  yes;
 otherwise:
  no.

No está mal y para esta historia es más que suficiente, pero ya que nos hemos puesto a generalizar, ¿podríamos cambiar el código para que cualquier cosa que se pueda encender con fuego pueda ser encendido por cualquier PNJ además del interlector? ¡Sí! Tenéis que definir adecuadamente las cualidades de esos objetos o la 'clase' a la que pertenecen... y os lo voy a dejar como ejercicio.

Hablando de la protagonista. Inform 7 permite examinarte a tí mismo con comandos como 'examináme' ó 'exme' y la respuesta por defecto no puede ser más inadecuada para una anciana, ¡probadlo! (hay que probar todo lo que se os vaya ocurriendo). ¿Cómo se cambia esto? Es fácil el jugador no es diferente a cualquier otro objeto de la obra así que:

Chapter 4 - El interlector

The description of the player is "Los años han hecho mella en tí, pero aún mantienes cierta compostura.".

Y vamos a dejarlo aquí por hoy. El estado actual de la obra podéis descargarla aquí.


8.6.18

Tutorial de creación de ficción interactiva - Huesos (11)

Para poder avanzar un poco más tenemos que buscar una manera de incluir la variabilidad que conseguimos en Squiffy a la hora de ir abriendo tinajas en el relato. En aquella versión hicimos que los enlaces que implicaban una nueva tinaja fuesen apuntando a alguna de los posibles textos válidos hasta que, con un número mínimo de abiertas, se permitía que pudiese escogerse la tinaja del sacerdote e iniciar así la secuencia final. 

En realidad en el caso de una herramienta para ficción interactiva de parser como es la escogida (Inform 7), se podría hacer de una manera conceptualmente igual, es decir, ir capturando la secuencia de 'abrir tinaja' que el interlector vaya tecleando y escoger el siguiente mensaje de descripción aleatoriamente y seguir avanzado. Esta sería la forma natural de hacerlo en tiempos antiguos cuando lo habitual eran cosas como PAWS, o el DAAD, que parece que ahora insisten en resucitar. A fin de cuentas estas herramientas estaban fuertemente orientadas al tratamiento del comando tecleado, haciendo bastante más difícil montar una lógica del mundo más general y más robusta. Los herederos de primera generación (SINTAC, NMP, CAECHO?, SKC), segunda (Paguaplús,Superglús, AttoPAWS) y actuales (NgPAWS) de estas herramientas, no han cambiado en nada esto. Los sistemas de parser orientados a objeto (como el Inform 6 o el AGE) cambian la situación pero no del todo, ya que el modelado por clases permite montar el modelo de mundo necesario, e incluir la aleatoriedad de una forma no necesariamente orientado al comando. Sin embargo, en ambos casos el hecho de que el tratamiento de los comandos está incluido en la definición de los objetos hace que siga siendo más natural orientar la solución a 'contar las veces que se usa abrir tinaja' e incluir respuestas aleatorias. Pero esta aproximación, que parece la más natural y sencilla de hacer, tiene en realidad muchos problemas de coherencia cuando se va más allá de la secuencia de comandos que se espera que el interlector use. Es fácil que el interlector acabe viendo las 'bambalinas' porque la respuesta que se le da a 'abrir la siguiente tinaja' simplemente no está del todo alineada con el modelo de mundo que de verdad está manejando el parser.

La aproximación de reglas propuesta por Inform 7 (aún estoy esperando a que salga alguna otra herramienta con esta aproximación) permite, por fin, desligar totalmente el modelado del mundo del tratamiento del comando y de hecho lo natural en esta herramienta es hacerlo así. Veamos cómo...

Lo primero es que vamos a rellenar las tinajas con 'contenidos' de verdad, o sea, cada tinaja va a tener un objeto (thing en I7) en su interior cuya descripción es el equivalente al mensaje aleatorio que teníamos en Squiffy. Como vamos a hacer muchas cosas generales con estos objetos lo natural en I7 es crear una clase de objetos para ellos, de esta forma:

A contenido is a kind of thing.  The plural of contenido is contenidos.

Una vez definida la clase podemos usar la capacidad que tiene I7 de crear múltiples objetos usando tablas de esta forma (véase sección en el manual):

Some contenidos are defined by the Table of Contenidos Tinajas. 

Table of Contenidos Tinajas
contenido description
a contenido Belaiska "El olor es aún intenso dentro de la tinaja pero el cuerpo  ya sólo 
era un pequeño montón de huesos.  Esta es la tinaja donde enterrásteis a Belaiska, la mujer de tu hermano, muerta de parto."
a contenido guerrero "Entre otros huesos de tamaño considerable, una calavera enorme 
te mira con resplandecientes dientes blancos."
a contenido niños "Varias calaveras, pequeñas, tal vez de niños acompañadas por sus 
huesesillos. Eso te hace pensar en todos los niños que morían durante el nacimiento o poco 
después de nacer, sin haber disfrutado si quiera de una breve vida con sus padres y familiares."
a contenido campesino "Huesos de un campesino, o una campesina, no muy diferente a tí. 
Ningún adorno, ni siquiera un minúsculo ídolo de los dioses que le acompañe y guie por 
las turbulenta noche del más allá. Sólo huesos cansados y desgastados."
a contenido polvo "Nada más que polvo. Es triste. Hasta ese polvo amarillento 
merece acompañaros al sur, pero no puede meterse en los sacos. Si hubieses traído 
sacos para harina... pero son caros y están todos ocupados con alimentos, son necesarios 
para los vivos."
a contenido antiguo "Esta tinaja debe ser muy antigua, pero los huesos debieron 
ser de alguien fuerte y resistentee porque aún quedan bastantes fragmentos entre el 
polvo."
a contenido reina "Debe ser el cuerpo de una princesa o de una reina, o tal 
vez de un cacique. Entre los huesos y el polvo sobre salen joyas. Pura vanidad 
envasada en barro."
a contenido sacerdote "¡No puede ser! Huesos teñidos de ocre, cuentas de piedra 
de bosque, el jade tosco pero sagrado y restos de tejido rojo. ¡Un sacerdote! 
¡Pero eso es imposible!"

Cuando quieres hacer  una obra con muchos objetos que sean de diversas clases, lo que acabamos de hacer es una forma estupenda de organizarlo y de que queden claros. Es compacta, fácil de mantener y la capacidad de I7 de extender/repartir tablas a lo largo de tu obra te simplificará aún más el trabajo (véase en el manual).

Cómo hacemos ahora que los contenidos estén en distintas tinajas, pues primero vamos a definir que una tinaja está vacía si no tiene contenido (lo que nos resultará seguro muy útil más adelante) de esta forma:

Definition: a tinaja is empty if there is no contenido in it.

Y ahora aprovechándonos de ello haremos:

When play begins:
 repeat with content running through contenidos:
  move content to a random empty tinaja.

'Definition:' es la forma que tiene Inform 7 de definir nuevos 'adjetivos' para las clases, condiciones que se pueden usar en otras frases del lenguaje, y 'random' permite escoger en un conjunto de números, objetos, etc... de forma tan general por eso es posible escribir algo tan simple y comprensible como 'a random empty tinaja'.

Como hemos creado ocho contenidos diferentes tendréis que subir el número de tinajas presentes hasta ocho, ya podéis imaginar que es con:

There are eight tapas.
There are eight tinajas.

Si corréis la obra y tecleáis 'tree' veréis las tinajas y cómo cada contenido ha acabado dentro de una de ellas. ¡Bien! Hemos creado casi todo lo que necesitamos para poder hacer funcionar nuestro relato.

Un par de cosas antes de continuar: primero, como habréis visto, hemos cambiado considerablemente los textos del contenido de las tinajas entre la versión de Squiffy y esta. Es lo normal. No sólo es el cambio necesario de tiempo verbal para hacer al interlector el protagonista (aunque esto en realidad podríais escoger no hacerlo en segunda del presente, pero no lo hagáis hasta que seáis expertos), además es que hay que ser cuidadosos con el texto de respuesta y reservar cosas para los examinar posteriores que ya veremos en otro capítulo. (Por cierto, un ejemplo de que podéis 'documentaros' incluso sobre la marcha en estos tiempos: he necesitado casi crear la descripción de la tinaja del sacerdote, he pensado en ponerle unos abalorios de piedras y no de oro, buscando sobre la época he llegado a esto, y rápidamente he visto que no hay nombre común para la variscita, así que he decidido crear uno).

Antes de despedirnos por el momento, ¿lo que hemos hecho con los contenidos no podríamos aprovecharlo para hacer que la descripción de las tinajas y sus tapas sea más coherente y así incrementar la credibilidad del modelo del mundo? Sí, de esta forma:

A tapa is a kind of supporter. 
The grammatical gender of a tapa is usually feminine gender.

Table of Description Tapa
text
"Envejecida, pero aún se reconoce la madera de los árboles locales, 
los mismos que os proveen de madera para cuencos o para cocinar."
"De madera vieja. Algo carcomida por el tiempo, 
pero aún reconocible como de los árboles locales."
"Madera envejecida por el tiempo aunque aún resistente, 
capaz de proteger los restos de los antepasados."

A tinaja is a kind of closed openable container. A tinaja is usually fixed in place.
All the tinajas are part of conjunto tinajas.
The grammatical gender of a tinaja is usually feminine gender.

Table of Description Tinaja
text
"Arcilla amarilla con algunos toques de rojo muy 
pálido cocida en el horno comunitario."
"Barro cocido a fuego lento para ser duradero."
"Amasado por manos expertas y cocido en el horno comunitario."
"Tierra y agua de vuestro río, y fuego alimentado 
con la madera de vuestros bosques. Hasta ahora, 
muy pronto la palabra 'vuestro' ya no será la adecuada."
 
When play begins:
 repeat with jar running through tinajas:
  if there is a tapa (called selected) which is not part of anything:
   now selected is part of jar;
  choose a random row in Table of Description Tinaja;
  now the description of jar is text entry;
 repeat with tapa running through tapas:
  choose a random row in Table of Description Tapa;
  now the description of tapa is text entry. 

Podéis ver que la forma de escoger un texto aleatorio de una tabla es algo diferente, pero eso también lo podéis leer con detalle en el manual.

El estado en este punto de la obra lo podéis descargar aquí.