![]() | ![]() | ![]() | Recipientes, superficies y sub-objetos |
Este año ha sido bueno para la Sociedad (je, je). Este año, nuestros
miembros han puesto más cosas encima de otras cosas que nunca. Pero,
debo advertirles, no debemos dormirnos en los laureles. No, aún hay
muchas cosas, y no puedo enfatizar esto lo suficiente, que no están
encima de otras cosas.
'La Real Sociedad Para Poner Cosas Encima De Otras Cosas', Monty Python's Flying Circus, programa 18 (1970),
Las cosas pueden meterse o ponerse encima de otras cosas. Al menos en el mundo real. En InformATE esto también es posible, pero con una limitación. En realidad en InformATE podemos mover un objeto "dentro" de otro objeto, pero el significado de "dentro" es flexible y puede significar lo que más convenga al programador en cada caso. Es decir, lo que ocurre en realidad en nuestro programa es que los objetos están unos dentro de otros, pero lo que ve el jugador puede ser diferente. Un ejemplo: si tenemos el objeto agua dentro del objeto botella, podríamos decirle al jugador que "dentro de la botella hay agua". En cambio si tenemos el objeto libro dentro del objeto estanteria ya no queda tan bien decir que "dentro de la estantería hay un libro", en este caso quedería mejor "en la estantería hay un libro". Y si tenemos el objeto libro dentro del objeto mesa, pues podríamos también decir que "en la mesa hay un libro", o mejor aún que "sobre la mesa hay un libro". Así que el hecho 'estar dentro' (en términos de programa) puede significar 'estar encima' en términos del juego.
Un ejemplo más: si el objeto llave está dentro del objeto Manolo (recordemos que los personajes son también objetos para Inform), en este caso ya no queda bien ninguna de las frases anteriores, sino más bien: "Manolo lleva una llave" o "Manolo tiene una llave". De nuevo el hecho real es que hay un objeto dentro de otro, pero la traducción a palabras puede ser "estar dentro", "estar encima", "estar oculto por", "estar en posesión de", etc..
Esto implica una limitación: a la hora de traducir el hecho 'objeto dentro de objeto' a una frase como "libro sobre la mesa" o "libro dentro del cajón", la librería tiene que elegir la preposición adecuada ("sobre" o "dentro"). Para un objeto como la mesa siempre elegirá "sobre" y para un objeto como el cajón siempre elegirá "dentro". La limitación es que por tanto un elemento no puede tener cosas "dentro" y a la vez cosas "encima". Uno u otro. El programador tiene que elegir. Ahora veremos cómo:
Un objeto que tenga el atributo recipiente, puede tener cosas dentro. Un objeto con el atributo superficie puede tener cosas encima. Un objeto no puede tener los dos atributos a la vez (esto es una limitación de Inform, a veces molesta. Puede eliminarse con un esfuerzo extra de programación como veremos en el ejercicio ??). Tanto los recipientes como las superficies pueden contener un máximo de 100 objetos, si bien este número puede cambiarse (se trata de la propiedad capacidad de ese objeto).
El jugador sólo podrá meter y sacar cosas de un recipiente si éste tiene además el atributo abierto (o abierta que es un sinónimo). Si tiene el atributo abrible, el jugador podrá abrirlo y cerrarlo libremente con los verbos "ABRE/CIERRA", a menos que tenga además el atributo cerrojoechado. Si tiene este atributo, entonces ya no funcionarán los verbos "ABRE/CIERRA" sobre él. Si tiene el atributo cerrojo el jugador aún podrá abrirlo usando la llave adecuada. Algunos objetos no requieren llave y en ese caso el jugador puede quitarles el cerrojo con una orden como "QUITA EL PESTILLO AL COFRE", o bien "QUITA EL CERROJO AL COFRE" (y volver a echarlo con "ECHA EL CERROJO AL COFRE"). En otros casos el cerrojo sólo se abre si se usa la llave adecuada, en cuyo caso el jugador deberá poner "ABRE EL COFRE CON LA LLAVE ROJA" o algo similar. En cualquiera de los casos, el conseguir abrir la cerradura no implica que se haya abierto el objeto. El jugador debería poner a continuación "ABRE EL COFRE" (esto puede resultar antinatural a un jugador español, por lo que convendría redefinir la acción QuitarCerrojo del cofre para que automáticamente generase también la acción Abrir). La decisión de si el objeto que tiene cerrojo requiere o no una llave la toma el programador, usando para ello la propiedad con_llave de ese objeto. Si esta propiedad no existe para ese objeto (o si se le da el valor cero), el objeto se abre sin necesidad de llave. Si en cambio se le da como valor otro objeto, será este segundo objeto la llave que permita abrir el primero.
En un objeto que tenga el atributo superficie, el jugador podrá poner cosas con verbos como "PON LIBRO EN LA MESA", o "PON LIBRO SOBRE LA MESA". Esto podrá hacerlo siempre (una superficie no puede estar abierta o cerrada), y también los contenidos de la superficie serán siempre visibles con el comando "MIRA EN LA MESA". o "MIRA SOBRE LA MESA".
![]() |
En español la preposición "EN" puede significar "dentro de" o
"encima de", según el contexto. Por ejemplo "Mira en el armario"
significaría "dentro", pero "mira en la repisa" significaría
"encima". ¿Cómo debe interpretar el parser la orden "Pon moneda
en bolsa"? Caben dos interpretaciones: ponerla dentro de la bolsa,
lo cual sería la acción Meter moneda bolsa, o ponerla
encima, lo cual sería la acción PonerSobre moneda bolsa. La
ambigüedad la resuelve comprobando si el objeto bolsa es un
recipiente o no. Si el objeto es recipiente, la acción
generada será Meter, si no es recipiente la acción generada
será PonerSobre. Si resulta que el objeto tampoco es
superficie, esta acción no tendría éxito y terminaría con el mensaje
"Poner cosas sobre (el objeto) no servirá de nada".
|
Los recipientes y las superficies pueden reaccionar cuando se pone en ellos o se saca de ellos un objeto, mediante la captura de la "acción falsa" Recibir y DejarSalir respectivamente. Por ejemplo, en "Ruinas" (en otra parte futura del juego) podríamos crear un abismo que haga desaparecer todo lo que entra en él (y si el jugador es lo bastante tonto como para entrar, morirá). Este abismo puede programarse como un recipiente (puesto que admite "meter" objetos dentro):
Object abismo "abismo espantoso"
with nombre 'abismo' 'espantoso' 'negrura' 'pozo' 'profundidad'
'profundidades' 'sin' 'fondo' 'oscuridad' 'tiniebla'
'tinieblas',
reaccionar_antes [;
Saltar: <<Meterse self>>;
Ir: if (uno==obj_abajo)
<<Meterse self>>;
],
antes [;
Meterse: banderafin=1;
"Caes y caes a través del silencioso vacío de la
oscuridad";
],
despues [;
Recibir: remove uno;
print_ret (_El) uno, " cae silenciosamente en la oscuridad
del abismo.";
BuscarEn: "El abismo es profundo y sólo está lleno de
tinieblas.";
]
has escenario recipiente abierto;
|
Observar cómo la rutina antes maneja el intento de meterse en el abismo, matando al jugador. Por otro lado la rutina reaccionar_antes actuará antes incluso, averiguando si el jugador ha escrito "SALTA" (acción Saltar) o bien "BAJA" o "ABAJO" o "VETE ABAJO" (acción Ir hacia obj_abajo). En ambos casos convierte la acción solicitada por el jugador en la acción Meterse abismo, para que sea el propio abismo el que se ocupe de matar al jugador mostrando el mensaje apropiado.
Y en lo que respecta al abismo como recipiente, vemos que le hemos dado los atributos recipiente (para que el parser admita la orden "METER ALGO EN EL ABISMO" o "DEJAR ALGO EN EL ABISMO") y también el atributo abierto, para que el parser admita la orden "MIRA DENTRO DEL ABISMO" o "MIRA EN EL ABISMO" (si no estuviera abierto el parser respondería ante estas órdenes con "No puedes ver lo que hay dentro del abismo espantoso porque está cerrado.")
Cuando el parser determine que el jugador ha dejado algo dentro del abismo, lo que hará será mover el objeto en cuestión al interior del objeto abismo, tras lo cual le notificará al abismo, a través de su propiedad despues la acción Recibir . El abismo como vemos ante esta acción simplemente hace desaparecer al objeto en cuestión mostrando un mensaje apropiado.
Cuando el jugador escriba "MIRA EN EL ABISMO", el parser generará la acción BuscarEn. De hecho la acción BuscarEn significa para Inform "dime lo que hay en el recipiente". Ya que el abismo está vacío (pues él mismo se ha ocupado de eliminar los objetos que recibía) el mensaje estándar de la librería sería: "El abismo espantoso está vacío." Para evitar ese mensaje capturamos también la acción BuscarEn en la rutina despues del abismo (en este caso igualmente podríamos haberlo hecho en la rutina antes)
EJERCICIO 9 |
Programar una bolsa que se comporte como la siguiente (nota, los
objetos introducidos en la bolsa no desaparecerían, simplemente el
jugador no podrá sacarlos de nuevo, pero siguen en la bolsa):
Pista: ante la acción Recibir, la bolsa debe mostrar el
mensaje de cómo se contorsiona, pero esto será despues de
haber recibido realmente el objeto. Ante la acción
DejarSalir la bolsa debe negarse antes de que la
acción tenga lugar. |
![]() | Recibir y DejarSalir son ejemplos de lo que Inform llama "acciones falsas" (fake actions) que son generadas por el parser, pero no han sido explícitamente solicitadas por el jugador. |
![]() | La acción Recibir se genera tanto si el jugador ha solicitado poner algo dentro de otro objeto, somo si ha solicitado poner algo encima de otro objeto. En el raro caso de que el objeto necesite reaccionar de diferente forma al recibir "dentro" y al recibir "encima", puede consultar la variable accion_recibir que puede tener el valor ##Meter o bien ##PonerSobre, según cuál haya sido el verbo usado por el jugador. |
En "Ruinas" tendremos un cajón de embalaje que es un recipiente convencional:
Object embalaje "cajón de embalaje"
with nombre 'caja' 'cajon' 'embalaje' 'embalar',
inicial "Aquí está tu cajón de embalaje, preparado para
contener cualquier hallazgo arqueológico que puedes hacer,
y llevarlo hasta la civilización.",
antes [;
Coger, Sacar, EmpujarDir:
"El cajón de embalaje es demasiado pesado para que merezca
la pena moverlo. Y menos mientras tu expedición no se haya
completado.";
],
has estatico recipiente abierto;
|
No le hemos dado descripción al cajón, por lo que si el jugador pone "EXAMINA CAJON", la librería llevará a cabo su acción estándar. Para objetos normales consistiría en poner el soso mensaje "No observas nada especial en el objeto", pero para los recipientes, la acción por defecto cuando no suministran descripción será listar sus contenidos (o la frase "El cajón de embalaje está vacío." si no contiene nada).
Ahora supón que queremos crear un objeto que sea una televisión portátil con cuatro botones. Cada uno de los botones ha de ser un objeto diferente y la televisión un objeto más, en total cinco objetos. Pero es evidente que si el jugador coge la televisión y se la lleva, los cuatro botones deberían ir también con ella. La forma de lograr esto es hacer que los cuatro botones sean objetos dentro del objeto televisión, ya que la librería se ocupa cada vez que se mueva un objeto de llevar con él todo lo que tiene dentro. Ahora bien, la televisión no es un recipiente (si lo fuera, la orden "MIRA EN LA TELE" diría "dentro de la tele hay cuatro botones", lo cual queda muy mal). ¿Qué pasa si no le ponemos el atributo recipiente? Inform admite perfectamente que haya objetos dentro de otros objetos sin necesidad de que sean recipientes. El único problema es que la librería supone que el jugador no puede ver esos botones porque se hallan dentro de otro objeto y por tanto si el jugador intenta "PULSAR BOTON", la librería no le dejaría.
La solución es dar al televisor el atributo transparente. De este modo la librería ya dejará al jugador referirse a los botones para examinarlos, pulsarlos o lo que sea. Si intenta coger uno, no obstante, la librería se lo impedirá diciendo "Parece formar parte del televisor".
El atributo transparente se le puede dar también a un recipiente, y en este caso significa que la luz puede pasar a su través. Esto causa que el jugador pueda ver todo lo que hay dentro del recipiente, incluso si éste está cerrado (aunque no podrá tocar ni sacar los objetos del recipiente), y también que si mete un objeto luminoso dentro del recipiente, la luz saldrá fuera de él, iluminando la habitación, incluso si el recipiente está cerrado.
EJERCICIO 10 |
Basándote en lo que se ha dicho anteriormente, programa un televisor
que tenga un botón de encendido y una pantalla. Pista: la pantalla y
el botón serían objetos "dentro" del televisor, aunque el jugador
no debe saber esto, por lo que el televisor no debe ser
recipiente, sino transparente. (Solución) |
EJERCICIO 11 |
Escribe dos objetos: una caja metálica y otra de cristal, que se
comporten de forma diferente cuando se guarde una luz en su interior
y se cierre la tapa. (Venga, este es fácil: Solución) |
![]() | A veces ocurre que un objeto debe tener sub-objetos (como la pantalla y el botón del televisor) y a la vez, también contener objetos dentro. Por ejemplo, un microondas con sus botones pero dentro del cual se deben de poder meter cosas. En este caso la solución de hacerlo transparente sin ser recipiente no es satisfactoria. Para esto se puede usar la propiedad suma_al_alcance. Esta propiedad contiene una lista de objetos que la librería mantendrá siempre conectados (juntos), pero que no cuentan como "dentro" de él. Más detalles sobre el "alcance" y sus reglas en la sección sobre lo que hay al alcance del jugador. |
EJERCICIO 12 |
Programa una bolsa de redecilla que cuelga del techo. Dentro de ella
hay cosas que el jugador puede examinar, oler y escuchar (por
ejemplo, un reloj que hace "tic-tac"), pero no puede hacer ninguna
otra cosa con ellas. Pista: la bolsa es obviamente un recipiente
pero debe "reaccionar" ante cualquier acción que intente el
jugador, impidiéndolas todas menos las antes dichas. (Solución) |
![]() | ![]() | ![]() | Recipientes, superficies y sub-objetos |