|  |  | Rompecabezas un poco más complicados

## Rompecabezas un poco más complicados

Vamos a programar el rompecabezas de la funda. Se trata de que la orden COGE FUNDA fracase, a menos que el jugador antes haya cortado las correas con el cuchillo. ¿Cómo lograr esto?

Para empezar habrá que añadir un nuevo objeto: las correas. Lo primero es plantearse si estas correas son un objeto separado de todos los demás, que el jugador pueda coger y llevarse, o si forman parte de la propia funda, o si forman parte de la cama. Si forman parte de la cama, habrá que evitar que el jugador pueda cogerlas. Esto es fácil sin más que poner una respuesta apropiada ante la acción `Take (Coger)`, como por ejemplo: "Forman parte de la cama y no puedes llevártelas."

En cambio, si forman parte de la funda la cosa es un poco más compleja, ya que en principio el jugador no puede cogerlas, pero sin embargo si coge la funda, automáticamente debe coger también las correas. Inform está preparado para este tipo de situaciones. Es posible indicar que un objeto tiene "componentes" inseparables de él. Así, la funda tendría como un componente las correas. La librería maneja automáticamente esta situación de modo que si el jugador intenta COGER CORREAS, le dirá "Eso forma parte de la funda." Y no le dejará. En cambio, si consigue coger la funda de alguna forma, las correas también irán con él. Y si deja la funda en otra localidad, las correas también serán dejadas.

Para no complicar más la situación, haremos que las correas formen parte de la cama y por tanto no se puedan coger.

Una vez hayamos escrito el objeto `correas`, hay que programar el puzzle. Si el jugador pone CORTAR CORREAS CON CUCHILLO, marcaremos que las correas están cortadas (activando su atributo `general`). Esto lo haremos capturando la acción `Cut (Cortar)` en el objeto `correas`. Por otra parte, el objeto `funda` debe capturar la acción `Take` y permitir que tenga éxito sólo si las `correas` tienen activado `general` (esto es, han sido cortadas).

Ante la orden CORTAR CORREAS CON CUCHILLO, el parser generará la acción `Cut`, con `noun=correas` y `second=cuchillo`. Si el jugador pone CORTAR CORREAS, a secas, entonces `second` tomará el valor cero. Y si pone CORTAR CORREAS CON CARBON, por ejemplo, entonces `second` tomará el valor `carbon`. En nuestro código debemos comprobar que realmente `second` es el cuchillo, o bien cero (no se ha especificado con qué cortar), y si no es ninguno de ellos imprimir un mensaje como "Eso no vale para cortar."

Si el jugador pone CORTAR CORREAS sin especificar con qué, podemos hacer que el juego responda "Tienes que especificar con qué cortarlas.", pero personalmente creo que la jugabilidad mejoraría mucho si dotamos al juego de cierta "inteligencia", de modo que él mismo asuma que quiere cortarlas con el cuchillo, si el jugador lleva el cuchillo consigo.

Así pues, las diferentes situaciones a manejar son:

     SI ya estaban cortadas "Ya están cortadas." y terminar
     SI especifica con qué cortar,
        y no es el cuchillo "Eso no corta" y terminar
     SI no espeficica con qué cortar,
        y no tiene el cuchillo "Necesitas tener algo que corte" y terminar
     EN OTRO CASO cortamos las correas

Lo que se traduce en el siguiente código Inform (fíjate en la descripción, es una rutina que cambia ligeramente según las correas estén ya cortadas o no):

    Object correas "correas" Limbo
     with   name 'correas' 'correa' 'cuero',
            description [;
                print "Son unas correas de cuero que ";
                if (correas has general) "cuelgan de la cama.";
                "sujetan la funda a la cama.";
            ],
            before [;
             Take:
                "Las correas forman parte de la cama. No puedes
                llevártelas.";
             Cut:
                if (correas has general) "Ya las has cortado.";
                if (second~=0 or cuchillo) "Eso no corta.";
                if ((second==0) && (cuchillo notin player))
                    "Necesitas tener algo cortante.";
                give correas general;
                "Cortas las correas con el cuchillo.";
            ],
     has    female pluralname scenery;

Observa que las correas comienzan en el limbo. Deben moverse al dormitorio a la vez que la funda, es decir, al examinar el catre. De paso aprovechamos para corregir un pequeño bug que había en el catre de la versión anterior. Si te fijaste, al poner EXAMINA CATRE por primera vez, el juego dice "El catre está cubierto por una funda", y hace aparecer la funda. Al examinarlo la segunda vez dice "Sólo restos de paja cubren el catre", asumiendo que el jugador ya ha cogido la funda. Pero la descripción no es correcta si el jugador no la ha cogido. La paja debe mencionarse sólo después de que el jugador haya cogido la funda. Esto es fácil de corregir gracias a que Inform tiene un atributo llamado `moved` que se activa tan pronto como el jugador coge el objeto (en realidad este atributo podría haberse llamado `taken (cogido)` y su función sería aún más clara).

Asi que ahora el catre debe contener el siguiente código:

            description [;
                if (catre hasnt general)
                {   ! Hacemos aparecer la funda y la correa
                    move funda to Dormitorio;
                    move correas to Dormitorio;
                    give catre general;
                }
                if (funda has moved)
                    "Sólo restos de paja cubren la cama.";
                "Una funda de tela cubre la cama.";
            ],

Y la funda debe ser modificada para que impida la acción `Take` a menos que las correas hayan sido cortadas. Basta añadirle esto:

            before [;
             Take: if (correas hasnt general)
                 "La funda está sujeta a la cama por unas correas.";
            ],

Por otro lado, si el jugador consigue coger la funda, al examinar la cama una segunda vez se le dirá que está cubierta de paja. Resulta natural que el jugador intente ahora COGER PAJA, pero ¡la paja está todavía en el Limbo! Debemos traer la paja al dormitorio en el instante en que el jugador consiga coger la funda.

Para lograrlo haremos uso de otra rutina que tienen todos los objetos y que no habíamos necesitado hasta ahora. Se trata de la rutina `after`, que es llamada por Inform cuando la acción ha finalizado con éxito. La rutina puede realizar las acciones que sean convenientes, imprimir un mensaje si así lo desea, y retornar TRUE o FALSE. Si retorna TRUE, la librería Inform no generará ningún mensaje extra en pantalla. Si retorna FALSE, Inform generará el mensaje de éxito habitual, por ejemplo, ante la acción `Take` dirá "Cogido".

Así pues, podemos añadirle al objeto `funda` el siguiente código:

            after [;
             Take:
                if (paja in Limbo)
                {
                    move paja to Dormitorio;
                    "Con las correas cortadas logras coger la funda.";
                }
            ],

| Debes recordar algo muy importante: La rutina `after` solo es ejecutada para este objeto si la acción que intentó el jugador tuvo éxito. De hecho, cuando `after` sea ejecutada, la acción ya habrá terminado, y la funda ya estará en poder del jugador. Si intentó COGER FUNDA, pero la acción fracasó, el código anterior no será ejecutado.

Fíjate que, en caso de éxito, hacemos aparecer la paja, y mostramos un mensaje. Ya que se trata de un print implícito, tras mostrar el texto la rutina retornará TRUE, e Inform no añadirá nada más. Fíjate también que antes de hacer aparecer la paja y emitir el mensaje de éxito, comprobamos que la `paja` esté en el limbo. Si no lo está, no hacemos nada especial, por lo que Inform dirá su habitual "Cogida." Este detalle es para tener en cuenta el caso de que el jugador deje la funda en otro lugar y vuelva a cogerla más tarde. En ese caso el mensaje "Con las correas cortadas logras coger la funda." ya no tendría sentido, y de hecho no aparecerá, porque en ese caso la paja estaría en el `Dormitorio` y no en el `Limbo`.

Como de costumbre, aquí tienes la versión completa del juego para que lo estudies, lo modifiques a tu antojo y lo pruebes.

|  |  | Rompecabezas un poco más complicados