jueves, 20 diciembre

16:08

Remake de El Genio
[Informate tú (Herel)]

Ayer lo empecé, y acabo de terminarlo: el remake de El Genio. Aquella aventura de 1999, tan difícil debido sobre todo a la cutrez de la programación.
Ahora los eventos de tiempo funcionan como debieron hacerlo, y además he incluído sonidos.

Tabla periódica de los elementos aventureros
[Informate tú (Herel)]

Pincha sobre la imagen para verla más grande


¿Qué hace la gente en las aventuras?
[Informate tú (Herel)]

Cuando programaba mis aventuras en DISAC (un parser propio en C), incluí un contador interno de forma que conjuntamente con la posición se guardara una estadística de uso de cada acción, así como el número de veces que el jugador habia probado un verbo no contemplado... lo que vendrían a ser los "No entiendo lo que dices" o "No conozco ese verbo".
A grandes rasgos el resultado que ví, en las posiciones que pude conseguir de la gente, es que EXAMINAR era la acción estrella, y ésta conjuntamente con las acciones de movimiento (N,S,E,O) constituían más del 50% de las acciones de cualquier aventura.


Lo que por otra parte es bastante obvio ¿no? Antes de actuar hay que mirar, y después también, por si algo ha cambiado.
Desde otro punto de vista, también podríamos considerar a EXAMINAR como la acción más cansina. La abreviatura, por tanto, es fundamental, ex o x.

Parser para inútiles totales
[Informate tú (Herel)]

-¡Quiero un parser para inútiles totales! en el que no haya que aprender a programar.
-Disculpe, si no me equivoco usted habla cinco idiomas (por lo menos).
-Así es.
-Manda narices que haya hecho el esfuerzo para aprender cinco lenguajes humanos con sus complejas gramáticas, sus declinaciones, sus irregularidades, su léxico infinito, sus construcciones caprichosas, sus modismos... y no esté dispuesto a hacer el pequeño esfuerzo de aprender un lenguaje de programación cuya sintaxis viene a ser ridícula en comparación con la de cualquier lenguaje humano, y cuya lógica cabe en el cerebro de una hormiga.
¿Qué tiene que decir a esto?
...
-Bueno... es que con los lenguajes humanos se puede ligar...

Formas de conversación
[Informate tú (Herel)]

1. Conversación automática.
La conversación se desarrolla siguiendo un guión al margen de lo que pretendiera decir el jugador, detonada por una acción de hablar o cualquier otra.

2. Conversación por menús.
Al iniciarse una conversación se despliegan una serie de opciones con temas entre los que el jugador puede elegir, cada uno de los cuales generará una respuesta/reacción en el interlocutor que a su vez modificará (o no) el repertorio de opciones para el siguiente turno de habla del jugador.
En los modelos más simples las opciones simplemente van desapareciendo a medida que son escogidas y respondidas, de modo que el jugador sólo está eligiendo el orden en el que quiere que le cuenten las cuatro cosas que tiene que decir el PSI. No habría mucha diferencia entre esto y mostrar el diálogo entero de una tacada, a modo de conversación automática.
Los modelos más elaborados se asemejarían a un librojuego, donde la elección de una opción u otra abre y cierra caminos futuros.

3. Conversación por detección  de palabras clave.
Este es el sistema más conversacional, y quizá el más usado. En teoría es el más difícil pues supone un parser dentro del parser, y una aproximación a la programación de inteligencias artificiales; pero en la práctica nadie llega hasta tal punto y el programador se conforma con preveer un pequeño lexicón con lo importante.
Sus formas suelen ser del tipo DECIR A PERSONAJE "MENSAJE" o PERSONAJE, MENSAJE
Puede subdividirse en:
3.1. Reconocimiento de palabras clave estricto: Se buscará una o varias cadenas de texto, produciéndose error (mensaje tipo "no entiendo lo que dices") caso de que el jugador haya escrito algo que el parser no entienda. Da lugar a conversaciones muy pobres y básicas, del tipo:
DI A PERSONAJE "HOLA"
PREGUNTA A PERSONAJE POR LLAVE

3.2. Reconocimiento de palabras clave no estricto: Se buscará una o varias cadenas de texto, pudiendo generarse múltiples respuestas en función de las combinaciones de cadenas encontradas. El texto no reconocido se ignora. Mal visto tiene un gran margen de error, bien visto tiene un gran beneficio de la duda.
Nos permite diferenciar por ejemplo "Dónde está la espada" de "dame la espada" buscando las palabras que deben de aparecer fijo:
"donde" "espada" "dame" "entregame" "quiero"...
e ignorando las menos seguras y prescindibles, como:
"está", "(se) encuentra","(se) halla"...

3.3. Reconocimiento gramatical: es sencillo para órdenes (imperativas) simples usando el mismo motor que el analizador sintáctico del parser (que a fin de cuentas es lo que hace: reconocer un microlenguaje de órdenes imperativas VERBO+CD/CI/CC). Para otro tipo de enunciados sería más práctico recurrir al reconocimiento de palabras clave múltiples no estricto.

4. Conversación no lingüistica.
Acciones que provocan reacciones en los PSIS, como si fueran órdenes habladas. Mostrar objetos para obtener información sobre ellos, señalar una puerta, comunicarte por pitidos, golpes, claves...


Las conversaciones no dirigidas, es decir, aquellas en las que se detectan palabras clave, tendrán numerosas lagunas ante la inviabilidad de programar una inteligencia artificial que lo entienda todo. Podemos intentar disminuir, justificar o disimular el exceso de frases del tipo "No entiendo lo que dices" de diversas formas:

1. El PSI activo (no pasivo).
Si es el jugador quien tiene que abordar al PSI, quedarán más patentes sus defectos y sus fallas de programación, pero si es el PSI el que toma la iniciativa y dirige/orienta al jugador en todo momento sobre lo que se puede esperar de él, qué se le puede preguntar, qué le interesa... habrá menos margen de "Filomeno no parece haber entendido lo que dices".
Se trata de que el PSI hable al jugador sin necesidad de que éste le pregunte primero, y realice actividades por su cuenta en lugar de permanecer en una localidad a la espera.

2. El PSI sueco.
La lengua nativa del PSI es otra, y sus conocimientos sobre la lengua del jugador son escasos. Esto justificará que no reconozca la mayor parte de las cosas que se le digan.
El PSI también puede ser medio sordo o existir cualquier factor distorsionador que sea la causa del mal entendimiento.
El caso extremo es que el PSI no entienda abosultamente nada y por tanto responda inútilmente en su desconocido idioma. En este caso tan sólo se obtendrán reacciones útiles mediante comunicación no lingüística, al pronunciar nombres propios reconocibles al margen de la lengua (por ejemplo el nombre de alguien o de un lugar), o al hablar con el limitado léxico que el jugador aprenda del idioma de los PSIS.

3. El PSI autista.
No es más que sustituir las respuestas de error que informan que el PSI no nos ha entendido por otro tipo de respuestas que no digan expresamente que lo que hemos dicho no va a misa. "Filomeno espera a que acabes de hablar, y te da la espalda para asomarse por la ventana", "Filomeno medita unos segundos tras escucharte, y acto seguido vuelve a sus quehaceres.", "Por el gesto de aburrimiento, adivinas que a Filomeno no le ha interesado mucho lo que acabas de decir.". Da igual que las reacciones no concuerden con lo que se esperaría, el PSI te ha escuchado pero no has dicho nada que le interese o le motive a tener una reacción más propia.
Otra técnica en la misma línea son las respuestas evasivas, muy utilizadas en los programas de conversación con una IA, con frases como: "Muy interesante", "Cuénteme más sobre eso de 'quiero la llave'", "Estoy de acuerdo con lo que acaba de decir", "¡Eso es evidente!", "Cuando usted dice cosas como 'ayudame a abrir la puerta' yo cierro los ojos y escucho el mar"...

Enlaces:

Saboteur
[Informate tú (Herel)]

Ya puede considerarse terminada SABOTEUR, a falta de que decida hacer alguna ampliación.
Finalmente es una aventura 2D con interfaz conversacional, y no puede jugarse sin gráficos.

Las descripciones de las localidades no existen, salvo algunas impresiones del PJ en lugares relevantes. Las localidades se muestran gráficamente en 2D y tanto el PJ como los PNJ actúan en ellas conforme a los sucesos.
El resto de los textos usuales en una aventura conversacional sí que están incluídos.


Me ha costado horrores escoger el título, todos los que se me ocurrían me sonaban ridículos, demasiado largos, o pretenciosos, de modo que por pura desesperación he optado por "Saboteur", mismamente, como los juegos que inspiraron a éste.

[Actualización 14 de Septiembre]
La aventura puede descargarse AQUÍ. Ocupa 7 megas.

Desastre
[Informate tú (Herel)]

Blogger acaba de incorporar hace unos días una nueva funcionalidad para revisar el SPAM en los comentarios.
Entonces, de pronto aparecieron todos los comentarios del blog y me dió por pensar, así a las buenas, que sólo se trataba de una lista de revisión. Seleccioné todo y borré, pues no había nada que revisar.
Por hacer las cosas rápido y sin pensar resulta que se han borrado no sólo de la lista sino del blog.

Me he cargado sin pretenderlo los que cabían en la primera página de la lista de revisión, que son unos cuantos. Lo siento...

Los saboteurs
[Informate tú (Herel)]

En los 80 estaban de moda los karatekas y los ninjas, y de esto trataba la saga Saboteur.
En la primera parte, que no jugué, pero pude ver en casa de un chaval con un CPC monocromo tomábamos el papel de un ninja. En la segunda parte, que sí que tuve en mi CPC, encarnábamos a la hermana del anteriormente citado que debía ¿vengarse? infiltrándose en un complejo de unas 500 pantallas para desactivar el lanzamiento de un misil.
Los movimientos eran un petardo, propio de los juegos de la época, pero aun así la acción era trepidante, echándole imaginación y, en el caso de la segunda parte, gracias a la banda sonora, compuesta por Rob Hubbard (aunque mola más esta versión mejorada made in Spain).




El caso es que pretendo hacer algo parecido pero en plan conversacional.
Un ninja (o agente de negro) que se infiltra en una base enemiga compuesta por localidades bidimensionales, aunque en este caso con la posibilidad de traspasar puertas hacia terceras dimensiones.

No habrá animaciones, pero sí representaciones del personaje en las distintas acciones y posiciones.
Así, cada parte del decorado tiene sus coordenadas, y los objetos que dejamos también memorizan el lugar donde quedaron.
Al igual que en Randolph Dwight, el personaje se desplazará (aparecerá gráficamente desplazado) por la pantalla hasta el lugar donde se encuentre el objeto a manipular y en la pose adecuada para dar el pego de que está realizando dicha acción.
Es una mezcla de animación por turnos y por eventos de tiempo.
Así, si escribimos "coger pistola", el personaje aparecerá agachado unos segundos en el lugar donde yace la pistola (que también aparecerá representada en el suelo, aunque sean 4 pixels) y posteriormente se reincorporará.
Si saltamos tanto de lo mismo, el personaje no va a permanecer en el aire hasta que nos dé por escribir la siguiente orden y pulsar return.

Se diferencia de Barbarian Quest en que el personaje no se mueve, sino que aparece desplazado, y en que el interfaz es 100% conversacional.
Hasta ahora sólo había estado haciendo gráficos, pero hoy he programado la interfaz con unas pocas acciones y funciona bastante bien.

Las pantallas son de 800 por 200 pixels.
Primeramente dibujé las piezas para componer escenarios, los "ingredientes", pero en lugar de dibujar las pantallas a la antigua - -, lo cual sería una tortura china y consumiría mucho tiempo de proceso, grabé varios modelos básicos de escenarios ya compuestos a los que sólo habrá que añadir algunas partes externas para personalizarlos.
Por ejemplo, a un pasillo le puedo añadir puertas, muebles, muros laterales, y configurar así la decoración y las salidas de la localidad.
Glulx no tiene las capacidades de un lenguaje de programación de videojuegos: redibujado selectivo o volcado de buffer, por tanto dibujar muchos gráficos significa un lapso que se acaba notando, más si son PNG que si son JPG. Por tanto pego de base un JPG, e intento que los añadidos sean también JPG, salvo cuando no hay tu tía y necesito las transparencias de los PNG.

Tambien estuve barajando si usar una malla definiendo el mapa cómodamente en una matriz, y por ahora lo he descartado, ya que lo que me ahorro en mapeado me lo como luego configurando decorados con numeritos.
Serán localidades donde el decorado base se define en una propiedad, y los complementos en propiedades especiales acompañadas de las coordenadas del añadido, que sirven tanto para saber dónde se dibujan, como para tener la referencia de dónde tiene que ir el personaje si esa parte añadida es interactuable.
Así:
localidad lugar1 "lugar"
with
el_grafico pasillo1,
muroizquierdo 0,
escalerabaja 340,
;
Sólo con esto puedo automatizar desde la clase localidad que hay salida hacia el oeste, pero no hacia el este (pues existe la propiedad muroizquierdo); y que además se puede bajar por una escalera y el personaje cuando vaya a bajar o acabe de subir por ella se dibujará en la coordenada x=340.

Las puertas las meteré desde fuera, ya que como pueden estar abiertas o cerradas, y haber más de una por localidad (les pondré distintos colores), deben constituír cada una un objeto.

En Regreso al Edén ya hice una escena aislada así, donde el personaje era representado como en un arcade 2D localizado en la pantalla en función de su posición (la escena de cruzar el puente). Ésta vez será la base de la aventura.

Aunque no haya animaciones, creo que la acción va a ser igual de trepidante. Los resultados de las órdenes son instantáneos, y no hay que esperar cansinamente a que el personaje eche a correr y desaparezca por un extremo de la pantalla.

En Saboteur 1 el ninja llega a la base en una barca, en Saboteur 2 en un ala delta; y escapan respectivamente el helicóptero y en moto.
¿cómo puedo superar tal espectacularidad ochentera?

Aquí el ninja llegará a la base escondido en el camión de reparto de Mahou y escapará en una superbicicleta con cuadro de carbono y tubeless... por un carril bici, que ahora están de moda XD (Es broma, en parte)

Actualizo:
El juego sí que tendrá algunas animaciones de desplazamiento, pero parciales. No será el movimiento completo desde un punto hasta el destino sino los primeros pasos a modo de insinuación.

No tendrá descripciones, salvo particularidades, todo habrá que verlo en la pantalla, aunque los resultados de las acciones sí se describirán en texto escuetamente.
Lo que sí que se listan son los objetos pequeños, ya que debido a su tamaño, aunque aparezcan representados, son imposibles de reconocer (por ejemplo, una moneda serían dos píxels, podría ser cualquier cosa, incluso una textura de la pared)
También, incluiré algún comando de rastreo que liste los objetos de escenario de cada localidad, que se podrá configurar como permanente, para que los jugadores invidentes no tengan que estar tecleándolo constantemente.
Aun así, el resultado sin gráficos será muy pobre. La gracia de la aventura está en el feedback visual, aunque la alimentación sea textual. Será como "leer un cómic" :P

[Actualizo]
Parece que existe desde hace tiempo un remake un tanto libre de los Saboteur con el remix de Saboteur 2 Marcel Donné como banda sonora. Ver aquí.
El resultado no me gusta mucho, usa gráficos fusilados de otros juegos y con animaciones bastante chuscas.

Desambiguando en Inform6 (II)
[Informate tú (Herel)]

Vamos con el segundo ejemplo de desambiguación.
Esta vez vamos a hacer una caja de cerillas que contendrá cerillas de dos tipos:
1. Cerillas (esto no tiene ningún misterio)
2. Cerillas de la caja. (son las mismas cerillas de antes, sólo que están circunstancialmente dentro de la caja de cerillas, por si no quedaba claro).


Por tanto, tenemos que distinguir primeramente "cerillas de caja" de "caja de cerillas".
Esto ya lo hicimos en el ejemplo anterior con la leche y las jarras, pero con un mal resultado en cuanto intentamos interactuar con los dos objetos problemáticos a la vez en la misma orden. Ahora no ocurrirá así.

También debemos distinguir, como se anticipó, entre "cerillas" y "cerillas de la caja": las cerillas que tenemos en nuestra posesión o hemos sacado, de las que en esos momentos se encuentran en la caja.

El código, para InfSP, es el siguiente:

Constant Story "Desambiguación con Caja de Cerillas";
Constant ADMITIR_COMANDO_SALIDAS;
#Include "Parser";
#Include "Verblib";
[ Initialise;
location=habitacion;
rtrue;
];

!###########################################
object limbo "limbo";

object habitacion "habitacion"
with
description "...",
has light;

object jarron "jarrón" habitacion
with name 'jarron',
has container open;

object caja_de_cerillas "caja de cerillas" habitacion
with parse_name [ i j j2 j3 j4;
          j=NextWord();
          if (j=='caja'){!ee
                          i++;
                          j2=NextWord();
                          j3=NextWord();
                          j4=NextWord();
                          if(j2=='de'){if(j3=='las' && j4=='cerillas')i=i+3;
                                       if (j3=='cerillas')i=i+2;}
                          }!ee                             
          return i;
],


has female container openable ~open;

class cerillas
with short_name "cerilla",
plural "cerillas",
description [;
        if(self in caja_de_cerillas)"Una cerilla que está dentro de la caja de cerillas.";
        "Una cerilla normal y corriente.";
        ],

parse_name [ i j j2 j3 j4;
          j=NextWord();
          if (j=='cerilla')i++;
          if (j=='cerillas'){i++; parser_action=##PluralFound;}
          if (i>0 && action_to_be~=##Take or ##Remove){
                          j2=NextWord();
                          j3=NextWord();
                          j4=NextWord();
                    if(self in caja_de_cerillas){!¿está dentro de la caja?
                          if(j2=='de'){if(j3=='la' && j4=='caja')i=i+3;
                                       if (j3=='caja')i=i+2;}
                    }!¿está dentro de la caja?
                    }
          return i;         
],
has female;

cerillas c1 "" caja_de_cerillas;
cerillas c2 "" caja_de_cerillas;
cerillas c3 "" caja_de_cerillas;
cerillas c4 "" caja_de_cerillas;
cerillas c5 "" caja_de_cerillas;
cerillas c6 "" caja_de_cerillas;
cerillas c7 "" caja_de_cerillas;
cerillas c8 "" caja_de_cerillas;
!###########################################
! Procedemos a reemplazar el Parsenoun de la librería por el código de la
! librería Intnombre que hemos descargado. Con esto conseguimos que los
! adjetivos puntúen previa detección de un nombre.
Replace ParseNoun;
Include "IntnombreINFSP.h";
#Include "SpanishG";


Vamos a analizar este trozito de código del objeto caja_de_cerillas para ver lo que estamos haciendo:
with parse_name [ i j j2 j3 j4;
          j=NextWord();
          if (j=='caja'){!ee
                          i++;
                          j2=NextWord();
                          j3=NextWord();
                          j4=NextWord();
                          if(j2=='de'){if(j3=='las' && j4=='cerillas')i=i+2;
                                       if (j3=='cerillas')i=i+2;}
                          }!ee                
          return i;
],


En lugar de definir los nombres y los adjetivos definiéndolos previamente como de costumbre, vamos a mirarlos paso a paso con la función parse_name.

Nextword(); devuelve el valor de la siguiente palabra escrita, consecutivamente. Como la primera es el verbo (o cualquier texto conector de la gramática; o cualquier palabra supérflua que el parser decarte, como un artículo), el primer Nextword() leerá la segunda palabra.
Para que se entienda mejor, si de buenas a primeras escribiéramos:
Nextword(); Nextword(); j=Nextword();
la variable j leería la cuarta palabra que hemos escrito.

Bien, según el código de arriba, si la segunda palabra escrita es 'caja', le damos un punto y procedemos a comprobar las demás para aumentar la puntuación del objeto, utilizando las variables j2, j3 y j4 para almacenar la tercera, cuarta y quinta.
Y es que podemos referirnos a la caja (normalmente) con una cadena de hasta cuatro palabras:
caja
caja de cerillas
caja de las cerillas


De modo que si escribimos simplemente "caja", este objeto recibirá un punto; y si escribimos "caja de las cerillas" o "caja de cerillas" recibirá 1+2=3 puntos.
No conviene darle más puntos escribiendo sólo "caja", pues podría haber otra caja de otra cosa en la aventura, y nos cargaríamos la desambiguación. Así que sólo le subiremos la nota cuando detrás de caja hayamos escrito "de cerillas" o "de las cerillas".

Con el objeto cerillas:
parse_name [ i j j2 j3 j4;
          j=NextWord();
          if (j=='cerilla')i++;
          if (j=='cerillas'){i++; parser_action=##PluralFound;}
          if (i>0 && action_to_be~=##Take or ##Remove){
                          j2=NextWord();
                          j3=NextWord();
                          j4=NextWord();
                    if(self in caja_de_cerillas){!¿está dentro de la caja?
                          if(j2=='de'){if(j3=='la' && j4=='caja')i=i+3;
                                       if (j3=='caja')i=i+2;}
                    }!¿está dentro de la caja?
                    }
          return i;         
],


hacemos tanto de lo mismo, sólo que la palabra de vocabulario a detectar como inicio es 'cerilla' o 'cerillas'.
En cuanto detectamos la coincidencia le damos un punto y procedemos a rastrear el resto de las palabras que van detrás, de la misma forma. En este caso sólo les vamos a dar puntuación a las cerillas que además de haber sido descritas como "cerillas de la caja..." estén efectivamente dentro de la caja de cerillas.
De este modo, EX CERILLA y EX CERILLA DE LA CAJA nos dará dos descripciones distintas, tal como lo hemos programado.

¿Qué ocurriría si otorgáramos la puntución por igual a las cerillas dentro de la caja que a las de fuera?
Pues que por defecto, al examinar, el parser tomaría al azar una cerilla... pero priorizando las que están fuera de la caja (Ya hemos visto en el capítulo anterior que para el parser, ante la duda, la más salida, es decir, el objeto que no esté dentro de otro).
Por lo demás, meter y sacar cerillas funcionaría perfectamente.

Bien, vamos a compilar el código y a probar:

Puedes ver un jarrón (que está vacío) y una caja de cerillas (que está cerrada).
>x cerillas
No veo eso que dices.

Que no cunda el pánico. La caja está cerrada, y al no ser transparente no puedes ver las cerillas. De hecho no puedes saber si dentro hay cerillas, monedas o una araña famélica.

>abre caja
Abres la caja de cerillas, descubriendo ocho cerillas.

Ahora ya podemos verlas.

>x caja de cerillas
En la caja de cerillas ves ocho cerillas.

Correcto.

>x cerillas de caja
No puedes especificar objetos múltiples con ese verbo.

También es correcto, el parser ha detectado correctamente que nos referimos a las cerillas, sólo que no se pueden examinar en plural, y por eso lanza ese mensaje.

>x cerilla de caja
Una cerilla que está dentro de la caja de cerillas.

Probamos en singular, aunque esto no demuestra nada aún, ya que "cerilla de la caja" con cerilla en singular no entra en conflicto con "caja de cerillas" con cerillas en plural. Por tanto vamos a probar con una acción que a diferencia de examinar sí que admita plurales u objetos múltiples:

>sacar caja de cerillas
¡Pero si no está ahí ahora!

Primeramente hemos intentado el absurdo. El mensaje, aunque no muy claro, es correcto. Es el que lanza el parser por defecto cuando intentas sacar algo que no está metido en ningún sitio, y tal es el caso de la caja de cerillas.

>sacar cerillas de caja
cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada.

Como vemos, hemos sacado las 8 cerillas de la caja. Pero vamos a volver a meterlas para probar mejor la desambiguación:

>meter cerillas en caja
cerilla: Hecho. cerilla: Hecho. cerilla: Hecho. cerilla: Hecho. cerilla: Hecho. cerilla: Hecho. cerilla: Hecho. cerilla: Hecho.
>sacar cerillas de caja de cerillas / sacar cerillas de la caja de cerillas
cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada. cerilla: Sacada.

Ya, por fín, hemos enfrentado a las "cerillas de la caja" contra la "caja de cerillas" en la misma frase. Y como vemos el parser detecta correctamente a qué objeto nos referimos en cada una de las partes.

Alguien se podrá preguntar ahora... ¿Y qué pinta un jarrón ahí? Pues es para demostrar que no hay trampa ni cartón.
El jarrón es otro contenedor donde se pueden meter las cerillas. Si la caja de cerillas fuera el único contenedor presente, el parser no necesitaría detectar que nos referimos a ese objeto, y con escribir "sacar cerillas" o "meter cerillas" actuaría directamente sobre él. Por tanto no podríamos comprobar que efectivamente se está enterando de que nos referimos a ese objeto.
Es una más de esas características de Inform donde el parser se hace el listillo...

Pero aún no han terminado las comprobaciones. Vamos a volver a meter todas las cerillas en la caja y empezamos de nuevo:
>coge cerilla
Cogida.

(Aunque el mensaje por defecto -que podemos mejorar- no lo muestre, la cerilla cogida procede del interior de la caja, que es donde están todas.

>coge cerilla
Ya tienes la cerilla.

Obviamente ya tenemos la cerilla... aunque haya más dentro de la caja. Pese a que resulte pesado, vuelvo a recordar que en caso de empate Inform prioriza los objetos que no están dentro de otros, de modo que habiendo alguna cerilla fuera de la caja, ésta tendrá prioridad.
¿Qué ocurriría si hubiera más de una cerilla fuera de la caja? ¿Nos lanzaría el parser un mensaje de desambiguación para determinar a cuál de ellas nos referimos? No. Las cerillas están definidas como una clase, con las mismas propiedades de nombre (en este caso con la rutina parse_name), por tanto son equivalentes y se escoge una al azar, sin preguntar al usuario. No ocurriría así si hubiéramos definido alguna diferencia de vocabulario entre ellas, por ejemplo distintos colores. En ese caso el pasers nos preguntaría ¿A cuál te refieres, a la cerilla roja, a la cerilla azul, o a la cerilla verde?

Pero volvamos al tema:
>coge cerilla de caja / saca cerilla de caja
Sacada.

Si queremos coger las cerillas que están dentro de la caja, lo especificamos y listo.

>x cerilla
Una cerilla normal y corriente.

Ésta es la descripción de una cerilla que está fuera de la caja.

>x cerilla de caja
Una cerilla que está dentro de la caja de cerillas.

Ésta es la descripción de una cerilla que está dentro de la caja.

>coge dos cerillas de la caja
cerilla: Sacada. cerilla: Sacada.

Esto también funciona.

¿Queréis ver algo que no funcione?...
>mete en la caja de cerillas una cerilla
No entendí esa frase.

Pero esto no es un problema de desambiguación, sino de definición de gramática. Podemos ver cómo está definida la acción "meter" (siempre que hayamos compilado en modo debug) de la siguiente forma:

>xverbo mete
Verb 'coloca' 'echa' 'inserta' 'mete' 'pon'
     * multiexcept 'en' container -> Insert
     * multiexcept 'en' noun -> PutOn
     * multiexcept 'dentro' 'de' noun -> Insert
     * multiexcept 'sobre' noun -> PutOn
     * noun 'a' topic -> SetTo
     * 'a' creature 'en' container -> Insert
     * 'a' creature 'en' noun -> PutOn
     * 'a' creature 'dentro' 'de' noun -> Insert
     * 'a' creature 'sobre' noun -> PutOn
     * multiexcept 'encima' 'de' noun -> PutOn
     * 'a' creature 'encima' 'de' noun -> PutOn
     * 'cerrojo' / 'pestillo' / 'cierre' 'a' noun -> Lock
     * 'el' 'cerrojo' / 'pestillo' / 'cierre' 'a' noun -> Lock
     * 'cerrojo' / 'pestillo' / 'cierre' 'a' noun 'con' held -> Lock
     * 'el' 'cerrojo' / 'pestillo' / 'cierre' 'a' noun 'con' held -> Lock


Como vemos, no aparece por ningún sitio ninguna plantilla tal que 'en' container multiexcept.
Por tanto, si queremos que el parser entienda una orden con el complemento circunstancial por delante del complemento directo, debemos editar o ampliar esa gramática añadiendo las siguientes líneas:
* 'en' container multiexcept -> Insert reverse
* 'dentro' 'de' container multiexcept -> Insert reverse


Pero esto ya se sale del tema de la desambiguación y de la caja de cerillas.
Puedes descargar el código compilado para Glulx aquí:
http://www.caad.es/jarel/trastos/cajadecerillas.zip

Entradas anteriores

Feeds

FeedRSSLast fetchedNext fetched after
// infsp channel // XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
Aventuras Conversacionales 2.0 XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
caad – Xavier Carrascosa XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
CAAD: Club de Aventuras AD - Comunidad de Aventuras Conversacionales y Relatos Interactivos XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
El blog de Morgul XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
El Escritorio de Incanus XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
El interlector >_ XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
Ficción Interactiva – La Línea Dura XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
Fragmentarios XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
Informate tú XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
Interlecturas XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
La mano parlante XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
Las aventuras del arquero XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
Pacificaciones XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020
Primavera en los Cárpatos XML 16:08, martes, 26 mayo 2020 15:08, miércoles, 27 mayo 2020