CAAD

Comunidad de Aventuras Conversacionales y Relatos Interactivos
Fecha actual 20 Jun 2019 02:43

Todos los horarios son UTC + 1 hora




Nuevo tema Responder al tema  [ 14 mensajes ] 
Autor Mensaje
NotaPublicado: 04 May 2009 18:11 
Desconectado
Grafista
Grafista
Avatar de Usuario

Registrado: 04 Sep 2008 17:23
Mensajes: 734
Hola a todos. Me gustaría saber algo sobre los turnos en Inform/INFSP 6:

Entiendo que se avanza un turno cada vez que el jugador ejecuta correctamente
una acción. Sin embargo, si el comando produce un error (p.e. se intenta
hacer alguna cosa sobre un objeto que no se encuentra en la localización
actual del jugador), o el usuario teclea una meta-acción, la aventura
entiende que no se debe hacer avanzar el turno. ¿Es posible forzar a la
aventura a que se corra un turno ante un comando erróneo o una metaacción?


Una de las situaciones en las que me interesaba forzar el avance de turno era
cuando tengo un objeto con un daemon que imprime un mensaje
constantemente. Resulta que si el jugador intenta una acción que se entiende
como errónea, no se avanza un turno, y por tanto el daemon no imprime
nada. Gracias a Baltasarq ---muchas gracias por estar siempre respondiendo
a mis dudas--- he encontrado una forma de forzar al daemon para que se
ejecute siempre:

EDITADO: Como se explica en las respuestas de este hilo, el siguiente código NO FUNCIONA para forzar al daemon a que se ejecute siempre.

Código:
Room ...
 with before [;
         object.daemon();
         ...
        ],
 has light;


¿Pero es posible hacerlo de manera que lo que se fuerce sea el avance de
turno en lugar la ejecución del daemon? Es que ahora he intentado añadir a mi
programa una de las peculiaridades que incluye Blue Lacuna, de
Aaron A. Reed, en la que se imprime la descripción de la localidad cada vez
que se introduce una línea en blanco. Lo que he hecho ha sido alterar las
respuestas por defecto de la librería de esta forma:

Código:
!!------------------------------------------------------------------------------
!! Modificación de los mensajes por defecto de la librería
!!-------------------
Object   LibraryMessages
 with   before [;
       Miscellany:
      switch (lm_n) {
        10:   !! Se introduce una línea en blanco
         <<Look>>;
      }
   ];


Y, aunque es cierto que se imprime la descripción de la localidad como si el
jugador hubiese escrito > mira, la aventura creo que lo reconoce
como un comando erróneo y, por tanto, no se avanza el turno. (También
he intentado hacer: "[...] <Look>; TimePasses(); rtrue;", pero no funciona).

Creo que me he liado mucho con la explicación y no se si se entenderá algo...
En fin, gracias por ecucharme y ¡Un saludo!


Última edición por Makinaimo el 05 May 2009 13:43, editado 1 vez en total

Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 04 May 2009 19:01 
Desconectado
Implementador
Implementador
Avatar de Usuario

Registrado: 10 Mar 2004 11:58
Mensajes: 1817
Ubicación: Madrid
Parece que considera la acción de tipo meta (ya que, aunque alterado, viene de un mensaje de error)

Si tienes algún evento que deba cronometrarse podrías usar una variable en el daemon, por ejemplo "tiempo"
Código:
daemon[;
tiempo++;
consultasucesos();
rtrue;
],


y luego en el código donde haces el <<look>> interceptando el mensaje de error, lo dejas así:
Código:
tiempo++; consultasucesos();<<look>>;

y listo.

en consultasucesos(); meterías el código del daemon.
Código:
[consultasucesos;
if(tiempo==20) "Ha llegado tu hora, dice el verdugo... pero te dejaré vivir otros 5 turnos.";
if(tiempo==25)"Ahora sí que ha llegado tu hora.";
rtrue;
];

_________________
_/ /\ R e \_


Arriba
 Perfil  
 
NotaPublicado: 05 May 2009 03:52 
Desconectado
Semimomio
Semimomio
Avatar de Usuario

Registrado: 24 Ago 2007 00:41
Mensajes: 2023
Ubicación: Chile
Makinaimo escribió:
Código:
Room ...
 with before [;
         object.daemon();
         ...
        ],
 has light;


¿Pero es posible hacerlo de manera que lo que se fuerce sea el avance de
turno en lugar la ejecución del daemon?


Sí que se puede. Y tiene una forma muy sencilla de hacerlo. En primer lugar, quiero dejar en claro que me parece muy extraño que la rutina before() se ejecute incluso en un "no-turno" (cuando has escrito con error o escrito un metacomando). En cualquier caso, supongo que esto era un desconocimiento mío y si te funka bien, pues genial! :D

Ahora bien, he visto que en tu código usas TimePasses()... Para tus fines, esa rutina no te sirve para nada, porque es una rutina "punto de entrada" que TÚ MISMO debes implementar en tu código para hacer que algo se ejecute en cada turno. No es lo que queremos.

Para hacer lo que queremos debes recurrir a un "hack" más o menos feíto (dependiendo de cómo se mire) de la librería. La librería Inform tiene una rutina llamada...

Código:
InformLibrary.end_turn_sequence();


... que es la encargada de avanzar un turno en el mundo simulado. :D

Se usa en "contadas" partes de la rutina de parsing... pero nosotros podríamos usarla para lograr lo que necesitas.

Así que, podrías hacerlo de esta manera:

- En la propia rutina before() de tus localidades, poner una llamada a InformLibrary.end_turn_sequence().

:D Voilà! :)

Esta rutina también llamará a todos los demonios y relojes, así que no es necesario que llames a tu demonio luego de llamar a end_turn_sequence().

Eso sería. Espero haber ayudado un poquito. No he probado lo que te he escrito, pero no debería fallar. La rutina hace exactamente lo de avanzar un turno de juego, hace todos los cambios necesarios en el mundo simulado relacionados con avanzar un turno. Lo sé porque está comprobado. :)

En fin, que te sea útil. :D

Saludos!

_________________
Eliuk Blau
eliukblau (AT) gmail.com
http://www.caad.es/eliukblau/


Arriba
 Perfil  
 
NotaPublicado: 05 May 2009 09:34 
Desconectado
Semimomio
Semimomio
Avatar de Usuario

Registrado: 23 Abr 2004 08:49
Mensajes: 2918
Ubicación: España (Galicia)
Hola !

Eliuk Blau escribió:
En primer lugar, quiero dejar en claro que me parece muy extraño que la rutina before() se ejecute incluso en un "no-turno" (cuando has escrito con error o escrito un metacomando). En cualquier caso, supongo que esto era un desconocimiento mío y si te funka bien, pues genial! :D


Yo también dudo mucho el que funcione, francamente.
Yo lo pondría, más bien, en el reaccionar_antes del jugador, ese siempre funciona pues el objeto del jugador siempre está al alcance.

Citar:
- En la propia rutina before() de tus localidades, poner una llamada a InformLibrary.end_turn_sequence().


Bueno, si funciona, genial (lo digo por lo de la loc, no por lo de la rutina). Ya puestos, para no ponerlo en todas las localidades, yo crearía una clase.

Código:
class MyRoom
with
  before [;
         InformLibrary.end_turn_sequence()
         rfalse;
  ]
;   

MyRoom Loc1 "loc1"
class MyRoom
with
! ...
;


Creo que esto tiene un defecto, y es que en caso de que la acción sea fallida o meta, funciona perfectamente, pero en caso de que sea una acción normal, te haría pasar un turno de más por cada turno.

Salud !

Baltasar

_________________
-- Baltasar, el arquero


Arriba
 Perfil  
 
NotaPublicado: 05 May 2009 09:35 
Desconectado
Implementador
Implementador
Avatar de Usuario

Registrado: 10 Mar 2004 11:58
Mensajes: 1817
Ubicación: Madrid
Eliuk Blau escribió:
Esta rutina también llamará a todos los demonios y relojes, así que no es necesario que llames a tu demonio luego de llamar a end_turn_sequence().

Eso sería. Espero haber ayudado un poquito. No he probado lo que te he escrito, pero no debería fallar. La rutina hace exactamente lo de avanzar un turno de juego, hace todos los cambios necesarios en el mundo simulado relacionados con avanzar un turno. Lo sé porque está comprobado. :)


Pero... si bien en las acciones meta correría turno... en las acciones normales correría doble turno ¿no?

_________________
_/ /\ R e \_


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 05 May 2009 13:40 
Desconectado
Grafista
Grafista
Avatar de Usuario

Registrado: 04 Sep 2008 17:23
Mensajes: 734
Vaya, fallo mío. Claro que al meter object.daemon() en la rutina before de las habitaciones, el daemon no se ejecuta cuando tecleas mal un comando.

Estos últimos días he estado programando la aventura en descansos entre mis prácticas de clase y he añadido cosas sin pensar que, por supuesto, ahora no funcionan bien.

¿No hay manera de evaluar si el último comando introducido por el usuario es un metacomando o un comando erróneo? Para evitar eso de correr doble turno en acciones normales.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 05 May 2009 14:10 
Desconectado
Implementador
Implementador
Avatar de Usuario

Registrado: 10 Mar 2004 11:58
Mensajes: 1817
Ubicación: Madrid
Makinaimo escribió:
¿No hay manera de evaluar si el último comando introducido por el usuario es un metacomando o un comando erróneo? Para evitar eso de correr doble turno en acciones normales.


Prueba con:
Código:
if (meta==1) ... ! la última acción es meta
else... !no es meta

_________________
_/ /\ R e \_


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 05 May 2009 14:21 
Desconectado
Archivero
Archivero

Registrado: 19 Nov 2008 12:32
Mensajes: 268
Cóm va?


No has probado asi?

Código:
Object   LibraryMessages
 with   before [;
       Miscellany:
      switch (lm_n) {
        10:   !! Se introduce una línea en blanco
         <Look>;
         InformLibrary.end_turn_sequence();
    rtrue;
    }
   ];



El objeto LibraryMessages es una (o la) forma de redefinir los mensajes por defecto de la libreria, sean turnos o no-turnos.

Y en todos los casos, se realiza mediante la propiedad before (porque sí).

Particularmente para los no-turnos, la seccion Miscellany tiene todos los mensajes de error por defecto, mas otros mensajes no asociados a acciones.

En terminos de Zak; "Miscellany es una falsa acción, que se usa simplemente para agrupar allí todos los mensajes de error del parser, los mensajes ante algunos metacommandos, o algunos mensajes de librería no relacionados con acción alguna."


Puedes repasar todos los switch de Miscellany e incluir la llamada a tu daemon donde la necesites.


I6 tambien provee un punto de entrada para cuando ha procesado las ordenes y no le encontró sentido; llamado ParserError. Este punto de entrada se invoca justo antes de lanzar los mensajes de error (solo los mensajes de error).
Por defecto, en esa situacion se llama a los mensajes de Miscellany del tipo;
"No entiendo/No lo veo/etc" a partir del switch 27 hasta el 40 y pico.


Quizás tambien ayude que alli coloques la llamada a tu daemon o la llamada para forzar un turno.


La rutina ParserError la debes proveer tu:

Código:
[ ParserError etype;

        InformLibrary.end_turn_sequence();
   rfalse; // = 0; i6 imprime mensajes de error estandares.

];


Luego dinos que solución te vino mejor.

saludos!

_________________
I7 Spanish / Notas de desarrollo


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 05 May 2009 14:48 
Desconectado
Grafista
Grafista
Avatar de Usuario

Registrado: 04 Sep 2008 17:23
Mensajes: 734
La solución de lo que intento hacer creo que es algo parecido a esto:

Código:
Object   LibraryMessages
 with   before [;
       Miscellany:
      switch (lm_n) {
        10:   !! Se introduce una línea en blanco
         <Look>;
         InformLibrary.end_turn_sequence();
         rtrue;
        30:   switch (random(3)) {
         1: print "No encuentro eso que dices.^";
         2: print "No veo nada parecido por aquí.^";
         3: print "Parece que no hay nada de eso.^";
         } InformLibrary.end_turn_sequence();
         rtrue;
        38:   switch (random(5)) {
         1: print "¿Qué quieres decir con eso?^";
         2: print "Lo siento, no te entiendo.^";
         3: print "Intenta ser un poco más preciso.^";
         4: print "No comprendo eso que dices.^";
         5: print "¿Qué intentas decir?^";
         } InformLibrary.end_turn_sequence();
         rtrue;
      }
   ];


Los comandos meta siguen sin hacer que corra el turno, y estoy pensando que
tal vez, cuando se mete un comando erróneo, sólo me interesa que se
avance el turno en algunas localidades. Pero creo que la idea es más o menos esa.

No se si se puede programar mejor.


Última edición por Makinaimo el 05 May 2009 15:53, editado 1 vez en total

Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 05 May 2009 14:50 
Desconectado
Grafista
Grafista
Avatar de Usuario

Registrado: 04 Sep 2008 17:23
Mensajes: 734
Vaya, he escrito ese último mensaje sin leer el tuyo tesheñes...
a ver si le doy otra ojeada a mi solución.


Arriba
 Perfil  
 
NotaPublicado: 06 May 2009 03:54 
Desconectado
Semimomio
Semimomio
Avatar de Usuario

Registrado: 24 Ago 2007 00:41
Mensajes: 2023
Ubicación: Chile
jarel escribió:
Pero... si bien en las acciones meta correría turno... en las acciones normales correría doble turno ¿no?


Sí, y es exactamente por lo que dije que me parecía muy raro que le funkara bien usando before() en la localidad. Pero bueno, para diferenciar acciones META supongo que sirve el método tuyo de buscar el valor de la global "meta". :)

Es sólo cosa de cambiar el algoritmo.

Me imagino algo como...

Código:
Object LibraryMessages
  with
    before [;
      Miscellany:
        switch (lm_n) {
          10:   !! Se introduce una línea en blanco
            <Look>;
            InformLibrary.end_turn_sequence();
            rtrue;
          30: switch (random(3)) {
              1: print "No encuentro eso que dices.^";
              2: print "No veo nada parecido por aquí.^";
              3: print "Parece que no hay nada de eso.^";
            }
            InformLibrary.end_turn_sequence();
            rtrue;
          38: switch (random(5)) {
              1: print "¿Qué quieres decir con eso?^";
              2: print "Lo siento, no te entiendo.^";
              3: print "Intenta ser un poco más preciso.^";
              4: print "No comprendo eso que dices.^";
              5: print "¿Qué intentas decir?^";
            }
            InformLibrary.end_turn_sequence();
            rtrue;
        }

      ! agregamos esta para que no se avance un turno...
      ListMiscellany:
        rfalse; ! simplemente para que no interfiera con esta
        ! accion falsa (imprime anotaciones entre parentesis)

      default:
        ! para que la acciones META tambien pasen un turno
        if (meta==true) { InformLibrary.end_turn_sequence(); }

        ! esta es otra forma: si "meta" vale false, siempre se pasara
        ! un turno... Por lo tanto...
        !   meta = false;
        ! ... hara que todas las acciones no sean META, incluso
        ! aquellas que han sido declaradas como tales...
        ! (no estoy seguro si funciona, pero no pierdes nada
        ! con probar
   ],
;


Saludos! :)

_________________
Eliuk Blau
eliukblau (AT) gmail.com
http://www.caad.es/eliukblau/


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 06 May 2009 12:55 
Desconectado
Grafista
Grafista
Avatar de Usuario

Registrado: 04 Sep 2008 17:23
Mensajes: 734
Pues muchas gracias por la ayuda. A ver con qué os vuelvo locos la próxima vez...

Un saludo!


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 07 May 2009 12:56 
Desconectado
Grafista
Grafista
Avatar de Usuario

Registrado: 04 Sep 2008 17:23
Mensajes: 734
He encontrado un pequeño detalle que no funciona como debería. En mi caso no supone ninguna molestia porque he modificado la barra de estado en mi aventura, pero lo comento por si alguien más quisiese usar eso de refrescar la descripción de la localidad pulsando intro:

Cuando la barra de estado de la aventura lleva conteo de turnos, al pulsar intro se vuelve a imprimir la descripción de la habitación, pero no se refresca la barra de estado ---aunque el contador de turnos si que se incrementa en uno correctamente, no se pinta ese incremento---, algo que si que hace cuando se introduce el comando 'mirar'.

Código:
Turnos 0 :: > (se pulsa intro) ::> Turnos 0 ::> (se pulsa intro) ::> Turnos 0 ::> mira ::> Turnos 3


En cualquier caso, supongo que arreglar ese detalle sea algo muy sencillo.


Arriba
 Perfil  
 
NotaPublicado: 08 May 2009 09:39 
Desconectado
Semimomio
Semimomio
Avatar de Usuario

Registrado: 23 Abr 2004 08:49
Mensajes: 2918
Ubicación: España (Galicia)
Hola !

Supongo que todo se reduce a repintar la barra de estado cuando llamas a la rutina de final de turno.

Código:
InformLibrary.end_turn_sequence();
DrawStatusLine();


Yo diría que con esto debería solucionarse el problema.

Salud !

Baltasar

_________________
-- Baltasar, el arquero


Arriba
 Perfil  
 
Mostrar mensajes previos:  Ordenar por  
Nuevo tema Responder al tema  [ 14 mensajes ] 

Todos los horarios son UTC + 1 hora


¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado


No puede abrir nuevos temas en este Foro
No puede responder a temas en este Foro
No puede editar sus mensajes en este Foro
No puede borrar sus mensajes en este Foro

Buscar:
Saltar a:  
cron
Desarrollado por phpBB® Forum Software © phpBB Group
Traducción al español por Huan Manwë para phpBB-Es.COM