![]() | ![]() | ![]() | Puertas |
Una puerta es un tipo de objeto muy interesante y útil. No necesita ser literalmente una puerta, sino un objeto que sirva al jugador para acceder a otro lugar. Por ejemplo, una cuerda o una escalera. Para programar una puerta debes seguir los siguientes pasos:
Por ejemplo, continuando con "Ruinas", habíamos visto que la cámara lleva hacia el sur a un corredor. Programemos ese corredor de modo que en su lado sur tenga una puerta cerrada y bloqueada con llave que impide el paso al sepulcro (recuerda el mapa del juego). Deberás modificar el objeto Corredor que habíamos programado "en blanco" para que sea como sigue:
Object Corredor "Corredor de Techo Bajo"
with descripcion "Un corredor de sección cuadrada y techo muy bajo se
extiende en dirección norte-sur, obligándote a caminar
encorvado.",
al_n Camara,
al_s PuertaPiedra,
has luz
|
Le hemos puesto luz a esta habitación porque el juego todavía no está terminado, y no hemos programado aún ninguna antorcha o algo similar, y si no le hubiéramos dado el atributo luz no podríamos probar lo que llevamos programado, pues al entrar en esta habitación la librería simplemente diría "Está muy oscuro y no puedes ver nada". Por otro lado, como vemos, hacia el sur lleva al objeto llamado PuertaPiedra. La diferencia con otras habitaciones que habíamos programado antes es que PuertaPiedra no es otra habitación, sino una puerta que se programaría así:
Object PuertaPiedra "puerta de piedra" Corredor
with nombre 'puerta' 'gran' 'pesada' 'piedra' 'amarilla',
descripcion "Simplemente es una gran puerta de piedra",
si_cerrada "El paso hacia el sur está bloqueado por una gran
puerta de piedra amarilla.",
si_abierta "La gran puerta de piedra amarilla que se halla al
sur, está abierta.",
puerta_a Sepulcro,
direcc_puerta al_s,
con_llave LlavePiedra,
has femenino estatico puerta abrible cerrojo cerrojoechado;
|
Para que puedas compilar el programa, necesitas definir todos los objetos que se mencionan. En particular Inform se quejaría de que no has definido el objeto Sepulcro ni LlavePiedra. Vamos a darle una definición mínima simplemente para que pueda compilarlo y así poder probar lo que va de juego:
Object Sepulcro; Object LlavePiedra; |
Observar que es recomendable darle a las puertas el atributo estatico para evitar que el jugador pueda cogerla y llevársela por ahí. Las propiedades si_abierta y si_cerrada contienen texto que la librería mostrará cuando el jugador entre en la habitación que contiene la puerta. Sólo se mostrará una de las cadenas, según la puerta esté abierta o cerrada. Ya que inicialmente no le hemos dado el atributo abierta, esto significa que está cerrada. Si el jugador intenta abrirla mediante "ABRE PUERTA", recibirá el mensaje "Está cerrada con llave" (debido a que tiene el atributo cerrojoechado). Si el jugador intenta "QUITA EL CERROJO A LA PUERTA", la librería admitirá esa orden (porque la puerta tiene el atributo cerrojo), pero no podrá cumplirla porque esta puerta particular necesita una llave concreta para ser abierta. La llave necesaria es el objeto llamado LlavePiedra, tal como se indica en la propiedad con_llave. Así pues, tal como está, la puerta impide el paso al jugador (por otra parte, el objeto LlavePiedra, tal como lo hemos definido no aparece en el juego, ya que no le hemos puesto localización inicial, de modo que el jugador nunca podrá encontrarlo. Y aún si pudiera, no podría cogerlo pues no puede nombrarlo porque no le hemos dado nombres. La puerta nunca podrá ser abierta). Si estuviera abierta, al ser atravesada conduciría al lugar llamado Sepulcro, tal como se indica en la propiedad puerta_a. Por otro lado, la propiedad direcc_puerta vale al_s, lo que significa que la puerta se halla en el lado sur de la habitación.
Habrás observado que la puerta es de una sola dirección. Una vez que el jugador va en dirección sur y llega al Sepulcro, la librería no garantiza que encontrará allí la puerta (de hecho la puerta sólo está en el lugar llamado Corredor). Sólo hemos programado un lado de la puerta. Si crees que queda mejor que la puerta tenga dos lados, la cosa se complica un poco, ya que entonces este objeto debería aparecer en dos habitaciones a la vez. Esto no es difícil, para eso ya conocemos la propiedad esta_en, la parte complicada es que la propiedad puerta_a y puerta_hacia es diferente según desde qué lado se mire la puerta. La forma de lograr esto es hacer que estas propiedades sean en realidad rutinas, que consulten la variable localizacion para saber dónde está el jugador, y retornen el valor adecuado para una puerta vista desde esa localización. Es decir:
Object PuertaPiedra "puerta de piedra" Corredor
with nombre 'puerta' 'gran' 'pesada' 'piedra' 'amarilla',
descripcion "Simplemente es una gran puerta de piedra",
si_cerrada "El paso está bloqueado por una gran puerta de
piedra amarilla.",
si_abierta "La gran puerta de piedra amarilla está abierta.",
puerta_a [;
if (localizacion==Corredor) return Sepulcro;
else return Corredor;
],
direcc_puerta[;
if (localizacion==Corredor) return al_s;
else return al_n;
],
con_llave LlavePiedra,
esta_en Corredor Sepulcro,
has femenino estatico puerta abrible cerrojo cerrojoechado abierta;
|
Observa qué ha pasado con las propiedades puerta_a y direcc_puerta. Ahora son rutinas. La librería llamará a estas rutinas cuando sea necesario y éstas deben responder a dónde lleva la puerta (puerta_a o en hacia qué punto cardinal están orientadas (direcc_puerta). Las rutinas pueden hacer internamente las operaciones que deseen antes de responder, pero no deben imprimir nada en pantalla (prohibido usar print o variantes dentro de ellas). Como vemos en el ejemplo anterior, consultan la variable localizacion, que indica dónde está el jugador, para saber qué responder. Observar también cómo hemos modificado el texto de si_abierta y si_cerrada para eliminar las referencias de dirección de modo que la frase sea válida independientemente del lado desde el que se mire la puerta. Podríamos también haber hecho que si_abierta y si_cerrada fueran rutinas que consultaran la localizacion para generar un texto diferente según el caso.
A primera vista no está claro por qué las puertas han detener la propiedad direcc_puerta. ¿Para qué necesita una puerta saber en qué lado de la habitación está? La razón es que existen dos acciones diferentes para atravesar la puerta. Supongamos que la puerta está en el lado sur. El jugador puede escribir "VE HACIA EL SUR" (o simplemente "Sur"), lo que causará la acción Ir obj_s. Pero el jugador también puede poner "ENTRA POR LA PUERTA", o "PASA POR LA PUERTA", lo que causaría la acción Meterse puerta (la acción Meterse se genera cada vez que el jugador intenta entrar en cualquier objeto del juego. No confundir con la acción Entrar, que sólo ocurre cuando el jugador escribe "Entra", a secas, sin especificar objeto). Si la acción a ejecutar es Meterse puerta, lo que hará la librería será averiguar, a través de la propiedad direcc_puerta, que la puerta está en el sur, por lo que generará la acción Ir obj_s. Así que, aunque el jugador intente meterse en la puerta, la acción que finalmente se genera es Ir de todas formas. Esto facilita el trabajo al programador si quiere capturar la acción de ir hacia el sur.
![]() | A pesar de que el párrafo anterior procede del manual original de Inform, lo cierto es que la librería de Inform no se comportaba de este modo, sino que ante la acción Meterse puerta generaba finalmente la acción Ir puerta en lugar de Ir s_obj. Este bug está corregido en la librería InformATE. |
Así que por cualquiera de los caminos nos encontramos finalmente con la acción Ir s_obj ¿Qué hace la librería ahora? Mirará en la habitación la propiedad al_s, para ver a dónde lleva, y encontrará allí el objeto PuertaPiedra. Comprobará que esta puerta está abierta (si no, mostrará un mensaje diciendo que no puedes pasar) y si lo está consultará la propiedad puerta_a de PuertaPiedra para averiguar a qué habitación conduce la puerta, trasladando finalmente al jugador a ese lugar.
Esto tiene una consecuencia importante: Si quieres, por ejemplo, impedir que el jugador cruce la puerta bajo ciertas condiciones (por ejemplo, si lleva cierto objeto) aparentemente deberías escribir una rutina antes en la PuertaPiedra y capturar en ella la acción Meterse ¿no? La verdad es que ese enfoque sólo te funcionará si el jugador escribe "ENTRA POR LA PUERTA" o "VE POR LA PUERTA" o similar, pero no si pone simplemente "SUR" (en este caso la propiedad antes de la puerta no será llamada, ya que la acción generada es Ir s_obj, y la puerta no aparece como objeto directo).
Para casos como este tienes dos opciones:
EJERCICIO 13 |
Programa un puente que lleva al otro lado de un abismo, pero que se
viene abajo si el jugador lleva cualquier cosa en su
inventario. Pistas: el puente lo programarás como una puerta, en la
propiedad puerta_a comprobarás si el jugador lleva algo
(puedes usar la función children(jugador) que te devuelve
cuántos objetos lleva). (Solución) |
![]() | ![]() | ![]() | Puertas |