|  |  | Entendiendo Inform (y olvidando PAWS)

## Entendiendo Inform (y olvidando PAWS)

Tenemos bastantes rompecabezas en nuestro mini-juego, y esto va a involucrar muchas cosas nuevas: definir objetos, definir los comportamientos de esos objetos, etc... Para comprender realmente cómo se hacen estas cosas en InformATE es necesario conocer antes su filosofía, que es diferente en muchas cosas a la de PAWS. Por ello iremos muy despacio en el primer rompecabezas, y ya correremos más en los siguientes.

El primer rompecabezas que vamos a implementar será la puerta secreta. De momento, vamos a quitar la conexión que había entre la escalera y la mazmorra. Vamos, edita tu fichero y borra la línea que dice `w_to Mazmorra` dentro del objeto `EscaleraCaracol2`. ¿Ya lo has hecho? Compila el juego y juegalo de nuevo. Verás como ya no se puede ir al oeste desde la escalera. Sin embargo, sí que se podría aún ir al este desde la Mazmorra (¡si hubiera alguna forma de entrar en la mazmorra!), puesto que no hemos borrado esa salida. Inform, al igual que PAWS, permite conexiones asimétricas o ilógicas.

| Vamos a hacer un poco de trampa. Durante la fase de programación y pruebas puede resultar útil tener ciertos "superpoderes", que te permitan teleportarte y hacer otras maravillas dentro del juego. Muchos de estos "superpoderes" están activados por defecto en nuestro juego. Arranca el juego y escribe "VERSION", aparecerá el título del juego, y después información sobre la versión del juego y de la librería. ¿Aparecen las letras SD al final de esta línea? Si es así, tenemos los superpoderes (en realidad, esto indica que está activado el "modo Debug"). En la versión final del juego esto deberá estar desactivado, más adelante diremos cómo desactivarlo. Uno de los superpoderes es el de teletransportación. Para usarlo necesitas conocer el número de la localidad a la que vas a teletransportarte (¡como en el MUD!). Este es un número que Inform asigna a cada objeto del juego y que normalmente el programador no conoce. Podemos averiguarlo con el comando XLISTA, el cual nos mostrará todos los objetos del juego, y al lado de cada localidad, entre paréntesis, su número secreto. En nuestro juego saldrá algo como esto:
    > XLISTA
    Oscuridad (20)
    (Library Extensions) (24)
    Puerta Principal (26)
      a ti mismo
    Dormitorio (27)
    Escalera de caracol (28)
    Mazmorra (29)
    Escalera de caracol (30)
    Alto de la torre (31)
Aqui puedes ver que, además de las localidades del juego, hay dos objetos misteriosos. Uno llamado "Oscuridad" (con el número 20) y otro llamado "a ti mismo" (sin número). La Oscuridad es un lugar ficticio que existe en todo juego Inform, al que vas a parar tan pronto como te quedes a oscuras. "A ti mismo" es el jugador. ¡Ya te había dicho que el jugador es un objeto más! Además, fíjate que esa línea aparece un poco metida hacia la derecha, justo debajo de la línea que dice "Puerta Principal", lo que significa que en este momento, el objeto jugador está dentro del objeto `PuertaPrincipal`. Además hemos obtenido información sobre los números de las diferentes localidades, con lo que ya podemos teleportarnos a cualquiera de ellas. ¡Incluso a la Mazmorra a pesar de que no tenía entrada posible! Para ello basta poner el comando `XIR 29`. Si vuelves a usar `XLISTA` a continuación, verás como "a ti mismo" está ahora dentro de la `Mazmorra`. Comprueba, una vez teleportado, que puedes salir de la mazmorra si te mueves al este (irás a parar a la escalera de caracol), pero no puedes volver a entrar en la mazmorra yendo hacia el oeste, pues habiamos borrado esa conexión.

Lo que queremos ahora es que la conexión de entrada a la Mazmorra reaparezca mágicamente cuando el jugador intente EMPUJAR la antorcha, y desaparezca de nuevo cuando intente TIRAR DE la antorcha.

Para ello tenemos que crear el objeto antorcha. Esto es otra importantísima diferencia entre Inform y PAWS. En PAWS el jugador podía referirse a cosas que en realidad no existían como objetos dentro del juego (eran meros NOMBRES, pero no objetos). En Inform esto no es posible. Cualquier cosa a la que el jugador deba referirse, ha de ser un objeto.

Para comprender por qué, es necesario entrar a explicar con un poco de detalle las diferencias entre el parser de PAWS y el parser de Inform.

### La labor del parser: Acciones y Objetos

El parser es la parte del juego que lee una frase que el jugador ha escrito y la descompone en partes, tratando de asignar un significado a cada parte.

El parser de PAWS era muy sencillo, ya que lo único que hacía era comparar cada palabra de las que el jugador ha escrito con las palabras que el juego había definido en su vocabulario, tras lo cual asignaba una categoría diferente a cada una de estas palabras, ignorando sin más las no reconocidas. De este modo, al final del parsing se tenían en ciertas banderas:

- Qué verbo ha usado el jugador
- Qué nombre ha usado como primer nombre (y qué adjetivo)
- Qué nombre ha usado como segundo nombre (y qué adjetivo)
- Qué preposición ha usado.

A partir de aquí, el resto del trabajo correspondía al juego, que debía comparar el verbo usado por el jugador con cada posible verbo del juego, una vez encontrado, debía comparar el nombre usado por el jugador con cada posible nombre del juego, y una vez localizado, debía averiguar si ese nombre tenía sentido en la situación actual del jugador. Así, por ejemplo, ante la frase TIRA DE LA ANTORCHA, el parser simplemente se limita a decirnos que Verbo=TIRA, preposicion=DE, Nombre1=ANTORCHA. El programador debía hacer una serie de comprobaciones de este estilo:

      Si Verbo es TIRA
        y Nombre1 es ANTORCHA
           Entonces:
               Si el jugador esta en la escalera de caracol
                   ....
                   .... Instrucciones para abrir la puerta secreta
                   ....
               Si no
                   mostrar el mensaje ``No veo ninguna antorcha aqui''

En Inform, la mayor parte de estas comprobaciones las hace la librería. El programador debe escribir tan solo la parte que correspondería a las instrucciones para abrir la puerta secreta.

Pero antes de explicar cómo hace la librería para interpretar la frase, remarquemos dos conceptos clave de Inform: ACCIONES y OBJETOS. Estos conceptos marcan toda la diferencia entre Inform y los parsers tipo PAWS. Mientras no comprendas estos conceptos, no entenderás Inform. Repíte estas dos palabras todas las noches hasta quedar dormido, ACCIONES y OBJETOS, hasta que logres olvidarte de "verbos y nombres".

#### Acciones

| El jugador escribe VERBOS en sus FRASES. Sin embargo, lo que el juego recibe son ACCIONES. El Parser se ocupa de transformar FRASES en ACCIONES.

Un mismo verbo puede dar lugar a diferentes acciones, según la frase en que aparece. Fíjate: TIRA LA PIEDRA, TIRA DE LA ANTORCHA, TIRA LA PIEDRA CONTRA EL ESPEJO. El mismo verbo "TIRA", tiene significados bien distintos. En el primer caso significa algo como "dejar caer", mientras que en el segundo es más bien "dar un tirón" y en el tercero es "lanzar" o "arrojar".

El concepto de accion, pues, no es más que el significado de un verbo. El cometido del parser de Inform es analizar frases y convertirlas en acciones, es decir, extraer el significado de la frase. En la primera frase, "TIRA LA PIEDRA", la acción que genera el parser es `Drop (o sea Dejar)`, en la segunda frase "TIRA DE LA ANTORCHA" la acción que genera el parser es `Pull (o sea Tirar)`, y en la tercera frase "TIRA LA PIEDRA CONTRA EL ESPEJO", la acción generada es `ThrowAt (o sea Lanzar)`.

Es muy importante no confundir los verbos con las acciones. En los tres ejemplos anteriores el verbo ha sido el mismo "TIRAR", pero las acciones generadas han sido diferentes. Y la inversa también es cierta, hay muchos verbos diferentes que darán lugar a la misma acción. Así, la acción `Drop` puede ser generada por frases bien distintas: "DEJA LA PIEDRA", "SUELTA LA PIEDRA", "TIRA LA PIEDRA". Y la acción `ThrowAt` también puede ser generada por diferentes frases: "LANZA LA PIEDRA", "ARROJA LA PIEDRA", "TIRA LA PIEDRA CONTRA LA PARED".

| En PAWS el parser no intentaba "comprender" la frase, en Inform sí, y una vez comprendida, da lugar a una ACCION. En PAWS existían verbos sinónimos, en Inform lo que ocurre es que muchas frases distintas pueden dar lugar a la misma ACCION. Podría decirse que en Inform hay "frases sinónimas".

¿En qué se basa el parser para decidir que "TIRA DE LA ANTORCHA" tiene distinto significado que "TIRA LA PIEDRA"? No se conforma con examinar el verbo, sino que tiene que leer la frase completa para tratar de extraer un significado. En este ejemplo, el parser ha sido instruido para que, ante una frase que use TIRA seguida de la palabra DE, seguida de un nombre de objeto, la acción que genere sea `Pull`. Si, en cambio, la frase es simplemente TIRA seguida de un nombre de objeto (sin el DE), la acción será `Drop`. Finalmente, si la frase tiene la estructura TIRA <nombre de objeto> CONTRA <nombre de objeto>, entonces la acción será `ThrowAt`.

Esta información de qué acción debe generar para cada posible estructura de frase, no está incrustada dentro del parser de forma que sea imposible cambiarla. ¡Todo lo contrario! Se halla definida en un fichero aparte (`SpanishG.h`) y es bastante sencillo cambiarla, de modo que si tu lo prefieres, puedes hacer que TIRA PIEDRA genere la acción `ThrowAt` en lugar de `Drop`.

Por supuesto también es posible crear nuevas acciones, y asignarlas a nuevas estructuras de frase. Así, puedes crear la acción `Ayuda` (que no existe por defecto en la librería), y hacer que esta acción se genere ante las frases "AYUDA", "SOCORRO", "HELP". No obstante, la definición acciones y frases nuevas se dejará para más adelante.

| La librería Inform ya trae predefinidas un montón de frases y las correspondientes acciones para cada caso. Es importante que conozcas qué acciones se generan para cada verbo, ya que como programador tú te las verás únicamente con las acciones, y no con los verbos. Puedes consultar una guía rápida en InfoLib at your fingertips. Más adelante daremos un truco para saber qué acciones se generan ante cada posible frase, de modo que no necesites saber eso de memoria.

#### Objetos

La otra palabra clave que debes comprender es la del objeto, ya que:

| Las acciones actúan sobre los objetos. En PAWS, se programaban "tablas de respuestas" que indicaban qué responder para cada verbo, ante cada posible nombre. En inform en cambio los programas van "dentro" de los propios objetos, e indican qué debe responder ese objeto ante cada posible acción que se intente sobre él. Las acciones que el objeto no contemple, serán manejadas de forma automática por la librería.

Basta de teoría. Programemos de una vez el objeto antorcha para ver qué ocurre con él. Añade el siguiente código en tu juego. Puedes escribirlo en cualquier punto después del objeto `EscaleraCaracol2`, incluso podría ir al final del fichero. Sin embargo es buena idea ponerlo justo detrás de la `EscaleraCaracol2`, ya que de ese modo los lugares y los objetos que hay en ellos quedan juntos en el código.

    Object antorcha "antorcha" EscaleraCaracol2
     with   name 'antorcha',
     has    female;

Fijate en la estructura de un objeto, en realidad es casi idéntica a la estructura de una localidad:

- La palabra especial `Object` indica que va a comenzar la definición de un objeto. Esta definición terminará cuando aparezca un punto y coma (el cual aparece tras la palabra `female`).
- El nombre interno del objeto. Esto es equivalente al número de objeto de PAWS. Si te gusta pensar con números, puedes darle como nombre interno algo como `Objeto1`, `Objeto2`, etc.. Pero admitirás que resulta mucho más lógico llamarlo `antorcha`. Este nombre nunca lo verá el jugador (y no puede contener acentos ni eñes, ni coincidir con el nombre interno de ningún otro objeto del juego)
- El nombre corto del objeto, que debe escribirse entre comillas dobles. Este es el nombre que el juego mostrará cuando mencione el objeto (como en "Llevas una antorcha", o "Puedes ver una antorcha", etc)
- Y ahora, como novedad, aparece el nombre de otro objeto. En este caso se trata del objeto `EscaleraCaracol2`. Este otro objeto será el "recipiente" que contiene a la antorcha. Si es una localidad, esto significará que la antorcha está en esa localidad.
- La palabra `with` que da inicio a la lista de propiedades, al igual que en las localidades.
- La propiedad más importante que debe tener todo objeto, es su nombre. Te preguntarás ¿pero el nombre no era "antorcha", que ya habíamos puesto en la línea anterior? Y la respuesta es: no, "antorcha" es el nombre que usa la librería cuando tiene que emitir mensajes relacionados con este objeto. Sin embargo `name` es la propiedad que indica qué nombres puede usar el jugador para referirse a este objeto.

  En este caso particular, el nombre por el que el jugador se referirá será seguramente 'antorcha', pero este es el lugar donde podríamos poner más sinónimos (como por ejemplo 'tea'). Si quieres poner sinónimos, irían separados por espacios:

      with name 'antorcha' 'tea',

  | Los nombres que pongas en la propiedad `name` deben ir entre comillas simples (apóstrofes). Todas estas palabras las va recopilando Inform a medida que compila tu programa y las va metiendo en el Diccionario del juego. Inform no tiene una sección donde se le indique el vocabulario del juego, sino que él mismo lo va construyendo a medida que va encontrando palabras entre comillas simples como las anteriores. En estas palabras puedes poner acentos o eñes, pero se recomienda que no las pongas. Piensa que los juegos Inform pueden ser ejecutados en muchos ordenadores diferentes, algunos de los cuales ni siquiera tienen eñe en su teclado. Si pones en el `name` por ejemplo la palabra 'niño', estás forzando al jugador a que use esa palabra para referirse al objeto, ¡y tal vez el jugador no pueda escribirla! Si en cambio, usas 'nino' (con ene en lugar de eñe), todo el mundo puede escribirlo. Además, el juego comprenderá también la palabra 'niño' (con eñe), porque el parser convierte todas las eñes en enes si la palabra que puso el jugador no está en su diccionario. Lo mismo es aplicable para las vocales acentuadas.

- La lista de propiedades es corta en este caso, pues sólo le hemos puesto la propiedad `name`. Más adelante le daremos más.
- Finalmente, viene la lista de atributos que comienza por la palabra especial `has`.
- Como mínimo, un objeto ha de tener atributos que indiquen su género y número, para que Inform sepa qué artículo debe usar delante del objeto cuando se refiera a él. La antorcha es `female`. Algunos objetos pueden llevar también el atributo `pluralname` (por ejemplo "gafas").

  Si el género es masculino, puedes optar por poner el atributo `male` o no ponerlo (Inform presupone atributo `male` si no se pone).

- El punto y coma final da por terminada la definición del objeto.

Aquí tienes el código fuente del programa que incluye la antorcha, compílalo y tendrás la versión lista para jugar. Vamos a hacer muchos experimentos con esta antorcha, de modo que te aconsejo que sigas las explicaciones con el juego funcionando. Si pones VERSION en este juego precompilado, observarás que al final ya no aparecen las letras `SD`, sino sólamente `D`. La letra `D` indica que aún estamos en "modo debug" y por tanto seguimos disponiendo de superpoderes. La letra `S` indicaba además otro modo especial que no interesa para estas pruebas, y que es mejor desactivar. Para lograr desactivar el modo `S`, dejando activado el modo `D`, debes usar la siguiente orden al compilar:

     INFORM-631 -D -~S torre3.inf

¿Cómo se hace esto en JIF? Manejando el administrador de opciones de compilación (Build -> Switch Manager).
En la pantalla con las opciones, nos aseguramos que estén marcadas las opciones -D y -~S:
Una vez revisado esto guardamos las opciones pulsando en Save, y salimos de la pantalla pulsando Close.
Compilamos () y ejecutamos ().
Vamos con la primera prueba. Teclea XLISTA para ver cómo el nuevo objeto realmente forma parte del juego:

    >xlista
    Oscuridad (20)
    (Library Extensions) (24)
    Puerta Principal (26)
      a ti mismo
    Dormitorio (27)
    Escalera de caracol (28)
    Mazmorra (29)
    Escalera de caracol (30)
      una antorcha
    Alto de la torre (32)

¿Has visto? la antorcha está en la localidad número 30, la escalera de caracol. Vamos a teleportarnos allí. Puedes usar como antes el verbo `XIR 30`, pero ahora que la localidad contiene un objeto, puedes usar otra forma más cómoda: `IRDONDE ANTORCHA`, lo cual te teletransportará a la habitación en la que esté el objeto que tiene 'antorcha' en su `name`.

    > IRDONDE ANTORCHA
    Escalera de caracol
    Los desgastados peldaños de piedra resbalan en ocasiones. A mitad de la escalera
    una antorcha en la pared impide que la oscuridad sea completa.

    Puedes ver una antorcha.

Efectivamente, el mensaje "puedes ver una antorcha" nos ratifica que está en el lugar correcto. Realmente ese mensaje sobraba, puesto que la descripción de la localidad ya había mencionado la antorcha. Esto es muy fácil de corregir y después veremos cómo. Por el momento vamos a realizar algunas acciones sobre la antorcha.

| ¡Y este es un truco imprescindible! Otro de los superpoderes de que disponemos en modo "Debug" es el poder ver las acciones que genera el parser ante cada posible frase que tecleamos. Para ello pon:
    > ACCIONES
    [Action listing on.]
Y ahora intenta diferentes verbos sobre la antorcha, para averiguar qué acción genera cada uno. Como hemos dicho, el programador necesita conocer siempre las acciones generadas, pues la programación del juego ocurre en torno a las acciones (y no a los verbos como en PAWS).

Comprobemos que todo lo que os había contado antes sobre el verbo "TIRAR" es cierto, intentando las diferentes formas de este verbo y comprobando cómo cada una da lugar a una acción diferente:

    >tirar antorcha
    [ Action Drop with noun 31 (antorcha) ]
    Para dejar la antorcha deberías tenerla.

El mensaje entre corchetes ha aparecido porque hemos puesto antes `ACCIONES`. El mensaje que aparece a continuación es la respuesta estándar cuando intentamos dejar un objeto que no tenemos. ¿Qué significa el mensaje "[ Action `Drop` with `noun` 31 (antorcha) ]"?

En Inform casi todas las acciones recaen sobre algún objeto, aunque hay algunas excepciones (por ejemplo `Jump`, `Sing`, `Pray` son acciones que no necesitan objeto, mientras que `Take`, `Drop` etc son acciones que siempre han de ir referidas a un objeto: el objeto que se coge o se deja). Incluso en algunos casos se involucran dos objetos (como en la acción `Insert` que requiere el objeto que se está metiendo y el objeto dentro del cual se está metiendo).

El parser, después de analizar la frase y tras haber determinado el objeto (u objetos) sobre los que la acción tiene lugar, deja preparadas tres variables:

- `action`: esta variable contiene la acción que se ha generado
- `noun`: esta variable contiene el primer objeto relacionado con esa acción
- `second`: esta variable contiene el segundo objeto relacionado con esa acción

| En cierta manera, es algo análogo al verbo, el nombre1 y el nombre2 de PAWS, solo que en Inform no se trata de palabras, sino de acciones y objetos. El parser siempre intentará relacionar las palabras con los objetos del juego, y si no puede, causará un mensaje de error.

Volvamos a lo que ha dicho el juego: "[ Action `Drop` with `noun` 31 (antorcha) ]" Su significado debe de estar más claro ahora. La acción generada es `Drop` (aunque el verbo usado ha sido "TIRA"), y el objeto sobre el que recae la acción (lo que Inform llama "noun") es el objeto número 31 (que es la antorcha como nos aclara después entre paréntesis). El número de objeto no es importante para nosotros, es un número interno que Inform asocia a cada objeto. [Jeje, date cuenta que ahora que sabemos el número de la antorcha podríamos teleportarnos a su interior con `XIR 31` ¿qué crees que pasará?]

| Otro detalle importantísimo. Si el parser no es capaz de asociar la frase del jugador con un objeto válido en las cercanías, el parser se detiene con un error y la acción no llega a generarse. Esto se comprueba fácilmente en el juego. Ve al piso inferior (donde la antorcha ya no es visible) e intenta de nuevo poner "Tira antorcha". Veamos qué ocurre:
    >tira antorcha
    No veo eso que dices.
No aparece ningún mensaje entre corchetes indicando la acción ¡porque no ha llegado a generarse ninguna acción! El comando ha sido abortado porque no se ha encontrado el objeto sobre el cual se supone que debería actuarse. Esto es otra diferencia fundamental con PAWS, en donde el parser no intentaba asociar los nombres con los objetos, sino que se limitaba a dejarlos en una variable. Esto permitía que el juego pudiera reaccionar a nombres de cosas, sin que esas cosas existieran en realidad. En Inform esto no es posible. Cualquier cosa a la que el jugador deba referirse, debe ser un objeto del juego.

Sigamos experimentando con las acciones, viendo qué entiende el parser ante diferentes comandos:

    >salta
    [ Action Jump ]
    Saltas en el sitio, sin ningún resultado.

Fíjate cómo en este caso la acción que se genera no lleva objeto asociado (no se menciona el valor de `noun`). ¿Y si intentamos del mismo modo poner "DEJA" sin más palabras?

    >deja
    ¿Qué quieres dejar?

No se ha generado la acción `Drop`, porque el parser detecta que este es un comando incompleto. El parser ha sido instruído para que sepa que detrás del verbo DEJA debe ir siempre el nombre de un objeto. Como le falta esto, la acción ni siquiera es iniciada. (NOTA: Si al principio del código no se declarara la constante MANUAL_PRONOUNS, el paser trataria de deducir el objeto de forma implicita, 'adivinando' que se trata de la antorcha.)

Volvamos al piso de arriba e intentemos algunas acciones más sobre la antorcha.

    >coge antorcha
    [ Action Take with noun 31 (antorcha) ]
    Cogida.

Vaya. ¿Podemos coger la antorcha? Esto no debería ser asi, el jugador no debería poder llevarsela. Lo que ha ocurrido es que, dado que aún no hemos programado nada en el objeto `antorcha`, la librería ejecuta las acciones por defecto. Y por defecto, la librería permite coger cualquier objeto que se halle al alcance del jugador. Veremos después cómo impedirlo.

Podríamos seguir experimentando, pero te dejaré que lo hagas tú mismo. Intenta diferentes verbos sobre la antorcha. Prueba cosas absurdas, intenta abrirla, cerrarla, romperla, quemarla, olerla, lanzarla al suelo, empujarla, tirar de ella, girarla, moverla. Verás que Inform comprende todas esas frases y las convierte en diferentes acciones (o a veces en la misma, en particular fíjate en la acción que se genera para MOVER ANTORCHA).

Ahora pasemos a algo más interesante. Vamos a programar la antorcha para que "reaccione" ante ciertas acciones, evitando así que se ejecute la acción por defecto para esos casos.

### Cómo se ejecutan las acciones

Ya que queremos que en nuestro juego pasen cosas cuando el jugador empuje la antorcha, lo primero que debemos averiguar es la acción que se generará ante la frase "EMPUJA ANTORCHA". Para ello podemos usar la depuración de acciones como hemos hecho antes. Un buen juego deberia contemplar además otras posibles ideas que se le pueden ocurrir al jugador, como "EXAMINA ANTORCHA", "TIRA DE LA ANTORCHA", "MUEVE LA ANTORCHA", "GIRA LA ANTORCHA", etc. Así que aprovechemos ahora para indagar qué acciones se generan para cada una de esas frases:

    >empuja antorcha
    [ Action Push with noun 31 (antorcha) ]
    No ocurre nada, aparentemente.

    >examina antorcha
    [ Action Examine with noun 31 (antorcha) ]
    No observas nada especial en la antorcha.

    >tira de la antorcha
    [ Action Pull with noun 31 (antorcha) ]
    No ocurre nada, aparentemente.

    >mueve la antorcha
    [ Action Push with noun 31 (antorcha) ]
    No ocurre nada, aparentemente.

    >gira la antorcha
    [ Action Turn with noun 31 (antorcha) ]
    No ocurre nada, aparentemente.

Bueno, hemos averiguado que hay al menos tres acciones que deberíamos tener en cuenta en nuestro juego: `Push (Empujar)`, `Pull (Tirar)` y `Turn (Girar)` (fíjate que el verbo MOVER produce también la acción `Push`, esto es porque en el fichero `SpanishG.h` se ha definido así, aunque puede cambiarse. La asignación de verbos a acciones es programable).

Por otra parte `Examine (Examinar)` debería dar un mensaje un poco más descriptivo. Todo esto implica programar la antorcha.

| En PAWS las respuestas a los verbos se codificaban en el proceso llamado "tabla de respuestas". En Inform, en cambio, se codifican en cada objeto. Cada objeto lleva "incrustadas" las respuestas ante las posibles acciones.

Cuando el parser recibe una frase como "EMPUJA ANTORCHA", da los siguientes pasos:

- Analiza la frase, buscando en ella una estructura y comparándola con todas las estructuras que tiene pre-programadas (dichas estructuras se llaman 'líneas de gramática' en Inform). En particular, encontrará que la frase encaja con una escructura tipo "EMPUJA <algo>", donde <algo> ha de ser el nombre de un objeto que esté en las cercanías.
- Realizará entonces un bucle en el que recorrerá todos los objetos de las cercanías, a ver si encuentra alguno que pudiera ser una "antorcha". Esta indagación suele ser tan simple como comparar el `name` de cada objeto con la palabra "antorcha".
- Si no encuentra ningún objeto plausible, el parser inmediatamente finaliza, con un mensaje de error como "No veo eso que dices", y la acción no llega a generarse (el mensaje en concreto es programable también, pero este es el mensaje por defecto).
- Si encuentra un objeto llamado "antorcha", entonces el parsing ha tenido éxito. La variable `action` toma el valor `Push (o sea Empujar)`, y la variable `noun` toma el valor 31 (que representa al objeto `antorcha` en nuestro juego).
- Comienza la secuencia de actuación. En la secuencia de actuación, la librería da los siguientes pasos:
  - "Avisa" a todos los objetos que hay cerca, de que se va a intentar la acción `Push` con `noun`=`antorcha`. Cualquier objeto puede abortar la acción. Enseguida explicaremos cómo tiene lugar este "aviso" y cómo un objeto puede abortar la acción. Esto es útil, por ejemplo, para lograr que un PSI (Personaje Pseudo-Inteligente) cercano impida ciertas acciones (recuerda que un PSI es un objeto para Inform)
  - Si los objetos cercanos no ponen inconveniente alguno, la acción progresa un poco más, y entonces la librería "avisa" al objeto `antorcha` de que el jugador acaba de realizar la acción `Push` sobre ella. La `antorcha` debería tener preparada una respuesta para este caso.
  - Si la `antorcha` tiene preparada respuesta, se ocupará ella misma de continuar la acción. Aquí tiene lugar la programación de lo que ocurre al empujar la antorcha (la aparición de la salida oeste). La librería ya no hará nada más con respecto a esta acción. Es algo así como si la antorcha hiciera un DONE.
  - Si la antorcha no tiene preparada respuesta, entonces la librería ejecutará su acción `Push` por defecto. La acción `Push` por defecto se limita a escribir "No ocurre nada, aparentemente" (el mensaje también puede ser redefinido)
  - La acción `Push`, en particular, no hace nada más, puesto que no se ha cambiado el estado del juego. Todos los objetos permanecen exactamente igual a como estaban antes. Sin embargo otras acciones sí que cambian el juego. Por ejemplo `Take (o sea Coger)` o `Drop` cambia de sitio algunos objetos. En este tipo de acciones, la librería "avisa" de nuevo al objeto en cuestión de que la acción `Take` o `Drop` ha finalizado con éxito, por si el objeto quiere hacer algo, antes de que la librería imprima finalmente un mensaje indicador del éxito de la acción (como "Cogido", o "Dejado").

Esta forma de funcionar, aunque puede parecer complicada al principio, te libera en realidad de un montón de trabajo. Tu programa no tiene que ocuparse de verificar en qué localidad estás para decidir qué responder (como era habitual en PAWS), ya que ha sido el parser el que ha averiguado previamente si la antorcha está ahí o no.

Por tanto, resumamos otra vez el mecanismo:

| El parser determina si la frase tiene sentido, y asocia a la frase una `action` y un objeto sobre el que recae la acción (siempre que haya un objeto de ese nombre cerca). Seguidamente la librería "avisa" a los objetos de que la acción tendrá lugar y si los objetos "no dicen nada", la librería llevará a cabo la acción por defecto.

¿Cómo "avisa" la librería a los objetos? Para que un objeto pueda ser "avisado" por la librería cuando una acción tiene lugar, el objeto debe proporcionar una rutina llamada `react_before` (entonces la librería le "avisará" de todas las acciones que tienen lugar en la proximidad de ese objeto, aunque la acción no vaya referida a él), o bien una rutina llamada `before` (entonces la librería le "avisará" sólo de las acciones que recaen sobre él, y no las que recaerían sobre otros objetos).

Olvidemos de momento la propiedad `react_before` y centrémonos en la propiedad llamada `before`. Esta propiedad se llama así como un recordatorio de que se activa antes de que la librería intente realizar la acción por defecto.

La propiedad `before` es en realidad una "rutina incrustada en el objeto". ¿Recuerdas que antes hablábamos de "rutinas libres", como la rutina `Initialise`? Ha llegado el momento de hablar de "rutinas incrustadas en los objetos".

Una rutina "incrustada en un objeto" es similar a una rutina libre en varios aspectos: se delimita mediante `[` y `]`, tiene una lista de variables locales y también una lista de instrucciones. Las principales diferencias son las siguientes:

- El nombre de la rutina no aparece después del `[`, sino antes de él.
- La rutina aparece dentro del objeto, como si fuera una propiedad de él (de hecho, en realidad es una propiedad del objeto).

Por ejemplo:

    Object antorcha "antorcha" EscaleraCaracol2
    with   name 'antorcha',
           saludo [;
                    print "Hey, soy una antorcha!^";
                  ],
    has female;

Hemos añadido tres líneas a la antigua antorcha. En ellas, hemos programado una rutina incrustada, llamada `saludo`. Fíjate como el nombre de la rutina va antes del `[`. Después del `[` iría la lista de variables locales, que está vacía en este caso, y un punto y coma. A continuación, la lista de instrucciones que componen la rutina. En este caso sólo hay una instrucción que es `print`. Finalmente, el `]` indica el final de la rutina. Es necesario poner una coma detrás de este `]` porque todo lo anterior era en realidad una propiedad del objeto `antorcha`, y las propiedades van separadas por comas. El resto del objeto es como antes.

¿Qué conseguimos añadiéndole una "rutina incrustada"? En realidad nada. Si juegas de nuevo con esta antorcha modificada, verás que el juego es exactamente el mismo. La antorcha tiene una rutina nueva, pero esta rutina no es utilizada por el juego. Podrías utilizar la rutina si, en otra rutina, pones lo siguiente:

    antorcha.saludo();

Esto es lo que se denomina una llamada a rutina incrustada. Como ves, las llamadas a rutinas incrustadas se forman poniendo, en primer lugar, el objeto del que forman parte, después un punto y detrás el nombre de la rutina. Finalmente, son necesarios los paréntesis (a veces dentro de estos paréntesis puede ir información extra, que se le envía a la rutina, y es copiada en sus variables locales, pero no en este caso puesto que la rutina no tiene variables locales).

Cuando el juego llega a una instrucción como la anterior, buscará el objeto `antorcha` (no importa en qué lugar del juego esté, en este caso no es necesario que esté cerca del jugador), y buscará dentro del objeto `antorcha` una propiedad llamada `saludo`. Si esta propiedad no existiera, se produciría un error durante la ejecución del juego. Si existe, entonces se ejecutarán las instrucciones que hay dentro de la rutina (en nuestro ejemplo, el `print` que imprime el saludo), y cuando se encuentre una instrucción `return`, o bien cuando se llega al final de la rutina `]`, el juego continuará por la instrucción siguiente a la llamada.

En cierta forma, todo esto es similar a ejecutar un proceso PAWS, pero en este caso los procesos están incrustados dentro de los objetos, y no se identifican por un número, sino por una pareja de nombres: el nombre del objeto y el nombre del proceso.

Bien, pero el caso es que nuestro juego no tiene ninguna instrucción que llame a `antorcha.saludo` y por eso el mensaje nunca será impreso.

Sin embargo, si en lugar de `saludo` hubieramos llamado a la rutina `before`, el mensaje aparecería cada vez que se intentara hacer algo con la antorcha, ya que la librería se ocupa de llamar a `antorcha.before` cada vez que detecta una acción con `noun`=`antorcha`. ¡Pruébalo! (tienes una versión modificada y lista para pruebas aquí

Si ejecutas esta versión, e intentas cosas con la antorcha, verás que el mensaje "Hey, soy una antorcha!^" aparece delante de cada respuesta de la librería. O sea, que la rutina `before` es ejecutada antes que la acción de la librería, no obstante no impide que la acción por defecto tenga lugar.

Para impedir que la acción por defecto tenga lugar, la rutina `before` tiene que ejecutar la instrucción `rtrue` (que viene a ser como el DONE del PAWS). `rtrue` significa "retorna VERDAD"; podemos imaginar que la librería le pregunta a la antorcha "¿verdad que ya te ocupas tú de realizar la acción?". Si la `antorcha` responde "VERDAD", entonces la librería ya no ejecutará la acción por defecto. Pero si la `antorcha` responde "MENTIRA" (`rfalse`), o no responde nada, la librería seguirá adelante con la acción por defecto.

¿Qué pasará por tanto si cambiamos la antorcha a esto otro?

    Object antorcha "antorcha" EscaleraCaracol2
    with   name 'antorcha',
           before [;
                    print "¡Dejame en paz!^";
                    rtrue;
                  ],
    has female;

¡El jugador recibirá la respuesta "Dejame en paz" ante cada posible acción que intente sobre la antorcha! Y además la acción no será realizada. En particular, el jugador no podrá coger la antorcha. Todas las acciones fracasarán con el mismo mensaje.

|  |  | Entendiendo Inform (y olvidando PAWS)