CAAD

Comunidad de Aventuras Conversacionales y Relatos Interactivos
Fecha actual 28 Sep 2020 20:47

Todos los horarios son UTC + 1 hora




Nuevo tema Responder al tema  [ 11 mensajes ] 
Autor Mensaje
NotaPublicado: 17 Jun 2009 11:35 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
La lista de cosas que se han hablado de mejorar, según las vaya echando en falta.

Por ejemplo:
Que al incluír un código externo desde el IDE, la línea aparezca completa, es decir con el método "world.getWorldPath()".

Editado para añadir al título, un tema que se trata en este hilo.


Última edición por jenesis el 13 Jul 2009 14:34, editado 1 vez en total

Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 22 Jun 2009 13:11 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
¿Cómo va el tema de los objetos metidos en contenedores?
Es el TODO que más me hace falta.
Si acaso no se pudiera avísame y busco una alternativa.

Un saludo
Jenesis


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 22 Jun 2009 17:04 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5312
Ubicación: Coruña
Pues lo estoy haciendo, sólo que este cambio es algo más complicado que otros (al menos es complicado hacerlo bien, de manera que no sea una chapuza y no cause problemas con otras cosas) y por eso estoy tardando.

Pero estoy ahora mismo tirando código en ello, y espero que hoy ya esté hecho y funcionando para *una* entidad.

Es decir, que por ejemplo puedas poner "frotar la lámpara" cuando la lámpara está dentro de una caja que está dentro de un baúl, sin tener que sacarla del baúl.

Me temo que hacerlo para dos entidades ("frotar la lámpara con el paño" cuando la lámpara está dentro de una caja, por ejemplo) aún me llevará algún día más, ¿necesitas esto también?

_________________
Actúa siempre de tal modo que las decisiones de tu voluntad pudiesen servir como preceptos de una legislación universal (E. Kant)


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 22 Jun 2009 19:46 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5312
Ubicación: Coruña
Bueno, la parte para una entidad creo que ya está funcionando correctamente:

Código:
COMANDO>>  i
Tienes una rosa y un clavel.

COMANDO>>  mirar la rosa
Una rosa es una rosa es una rosa.

COMANDO>>  oler la rosa
Hmm. Huele bien, la rosa esta.

COMANDO>>  poner la rosa en el baúl
Pones la rosa en el baúl.

COMANDO>>  oler la rosa
Hmm. Huele bien, la rosa esta. Y eso que está dentro de un baúl, ¿eh? Pero huele bien igual.

COMANDO>>  coger el baúl y ponerlo en el pozo
Coges el baúl.
Un bello baúl. Está abierto, y dentro ves una rosa.
Pones el baúl en el pozo.

COMANDO>>  mirar el pozo
Un pozo. Muy bonito. En su distante fondo hay un baúl.

COMANDO>>  mirar el baúl
Un bello baúl. Está abierto, y dentro ves una rosa.

COMANDO>>  oler la rosa
Hmm. Huele bien, la rosa esta. Y eso que está dentro de un baúl y a su vez dentro de un pozo, ¿eh? Pero huele bien igual.

COMANDO>>  coger la rosa y ponerla en la caja
Coges la rosa en el pozo en el baúl.
Una rosa es una rosa es una rosa.
Pones la rosa en la caja anti-olores.

COMANDO>>  oler la rosa
Al intentar oler lo que está dentro de la caja anti-olores, se activa un sofisticado mecanismo: suena una sirena, se encienden unos LED's, y no hueles nada de nada.


Esto se hace así:

En la rosa:

Código:
/*Método de análisis sintáctico de la entrada referida a una cosa*/
void parseCommand( Mobile aCreature , String verb , String args )
{
   if ( verb.equalsIgnoreCase("oler") )
   {
      aCreature.write("Hmm. Huele bien, la rosa esta.\n");
      end();
   }
}


void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
   if ( verb.equalsIgnoreCase("oler") )
   {
      Item theDirectContainer = path.get(1);
      Item theOtherContainer = null;
      if ( path.size() > 2 ) theOtherContainer = path.get(2);
      String message = "Hmm. Huele bien, la rosa esta. Y eso que está dentro de "
         + theDirectContainer.constructName(1,aCreature);
      if ( theOtherContainer != null ) message += " y a su vez dentro de "
         + theOtherContainer.constructName(1,aCreature);
      message += (", ¿eh? Pero huele bien igual.\n");
      aCreature.write(message);
      end();
   }
}


En el baúl, nada.

En la caja anti-olores:

Código:
void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
   if ( verb.equalsIgnoreCase("oler") )
   {
      if ( path.get(0).equals(self) )
      {
         aCreature.write("Como no podía ser de otro modo, la caja anti-olores no huele a nada.\n");
      }
      else
      {
         aCreature.write("Al intentar oler lo que está dentro de la caja anti-olores, se activa un sofisticado mecanismo: suena una sirena, se encienden unos LED's, y no hueles nada de nada.\n");
      }
      end();
   }
}


En suma, el método parseCommandOnContents es un método que se llama:

* Cuando se ha tecleado un comando sobre el objeto actual (self) y dicho objeto está dentro de uno o varios contenedores, o bien
* Cuando el objeto actual (self) es un contenedor, y se ha tecleado un comando sobre algo que está dentro del contenedor.

Los parámetros que se nos dan son:

Mobile aCreature: la criatura que ha escrito el comando.
String verb, String args: lo de siempre, el verbo y argumentos que ha escrito.
List path: una lista con el "camino" de contenedores que lleva al objeto. Por ejemplo, si el objeto es una rosa que está en una caja que está en un baúl, este path tendrá los objetos [rosa, caja, baúl], por ese orden.

Así, puedes hacer por ejemplo las siguientes cosas:

- Para que una acción sobre un objeto sólo se pueda hacer sobre objetos que tienes o que están en la habitación directamente (no contenidos en nada): defines el parseCommand sin más.
- Para que se pueda hacer también sobre objetos contenidos en algo: defines el parseCommand y el parseCommandOnContents. Si la acción es igual en los dos casos, puedes hacer que el parseCommandOnContents llame al parseCommand.
- Para hacer que se pueda hacer sobre objetos contenidos en contenedores de un cierto tipo pero de otros no: en el parseCommandOnContents, miras el path para controlar dónde está contenido el objeto.
- Para que un contenedor restrinja las acciones que se puedan hacer sobre objetos contenidos en él, o las modifique: defines el parseCommandOnContents del propio contenedor, que se va a llamar también sobre las acciones realizadas sobre objetos que estén dentro de él.

En breve lo tendrás en tu mail.

_________________
Actúa siempre de tal modo que las decisiones de tu voluntad pudiesen servir como preceptos de una legislación universal (E. Kant)


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 22 Jun 2009 21:05 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Muchas gracias!!
Lo pondré en práctica mañana mismo. :)


Arriba
 Perfil  
 
NotaPublicado: 23 Jun 2009 13:09 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Seguimos ampliando la lista:

2 Que no hagan falta más "IgnoreCase", que el sistema no haga diferencias por defecto entre comandos en mayúsculas o minúsculas.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 13 Jul 2009 11:01 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Al-Khwarizmi escribió:
Código:

....
void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
   if ( verb.equalsIgnoreCase("oler") )
   {
      Item theDirectContainer = path.get(1);
      Item theOtherContainer = null;
      if ( path.size() > 2 ) theOtherContainer = path.get(2);
      String message = "Hmm. Huele bien, la rosa esta. Y eso que está dentro de "
         + theDirectContainer.constructName(1,aCreature);
      if ( theOtherContainer != null ) message += " y a su vez dentro de "
         + theOtherContainer.constructName(1,aCreature);
      message += (", ¿eh? Pero huele bien igual.\n");
      aCreature.write(message);
      end();
   }
}


jenesis escribió:
Muchas gracias!!
Lo pondré en práctica mañana mismo. :)


Bueno... sólo me he retrasado tres semanas... :oops:

A ver, he estudiado la solución que has puesto para el tema de los contenedores y he llegado a la conclusión de que me crecen los enanos... o cómo se suele decir, "éramos pocos y parió la abuela..":(

Me pierdo Al*, esto me está empezando a sobrepasar, no sé si son las 3 semanas que llevo sin tocar el PUCK o es que mi cerebro ya no admite más métodos.

Duplicar el parseado de todo objeto suceptible de ser introducido dentro de otro, y encima con una sintaxis tan compleja me parece un trabajo descomunal.

No termino de comprender por qué el tema de los contenedores es tan sumamente complicado en AGE, cada objeto tiene su inventario, y el acceder a él como al del propio mundo debería ser cuestión de activar un simple "flag" en el caso de que el contenedor esté abierto.

contenido_accesible: si/no

¿Cómo hiciste para que un objeto que está en el inventario de otro responda a la acción "sacar" ? ¿No se puede hacer lo mismo para cualquier otra posible acción?

Yo agradezco mucho tu esfuerzo en atender mis peticiones, pero creo que si dejas esto así, estás condenando a Puck al fracaso.

Tiene que haber una solución más simple y a nivel interno sin que el programador vea tan agravada su tarea.

A ver, imáginemos una linterna.
Un objeto dentro de un contenedor abierto es como una puerta que está en dos localidades a la vez. El objeto está en dos inventarios a la vez, en el del contenedor y en de la localidad pero su estado encendida/apagada (abierta/cerrada) cambia a la par en ambas localidades porque realmente es solo un objeto.

¿No se puede hacer que todo objeto en AGE, se comporte como una puerta a nivel de contenedores?

Es más todo aquello que sea accesible para el jugador debería responder del mismo modo que respondería si estuviera en su propio inventario.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 13 Jul 2009 12:00 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5312
Ubicación: Coruña
jenesis escribió:
Duplicar el parseado de todo objeto suceptible de ser introducido dentro de otro, y encima con una sintaxis tan compleja me parece un trabajo descomunal.


Pero no tienes que duplicar código. Simplemente se trata de hacer que el parseCommandOnContents llame al parseCommand. O sea, tú escribes el parseCommand con todo tu código complejo para la acción, y ese parseCommand sólo se ejecuta si el objeto no está dentro de ningún contenedor. Pero después, tú escribes el parseCommandOnContents, y no duplicas el código, sino que haces que llame al parseCommand. O sea, una línea:

Código:
void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
   parseCommand(aCreature,verb,args);
}


De todas formas, si no te gusta esto, puedo hacer que el parseCommandOnContents funcione con todos los objetos, estén en un contenedor o no. De esta manera para hacer una acción que se ejecute sobre cualquier objeto esté o no en un contenedor, simplemente invocarías el parseCommandOnContents (a cambio, sería algo más complicado hacer acciones que se ejecuten SÓLO sobre objetos que están en un contenedor, porque requeriría comprobar el path). ¿Esto te parecería mejor?

_________________
Actúa siempre de tal modo que las decisiones de tu voluntad pudiesen servir como preceptos de una legislación universal (E. Kant)


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 13 Jul 2009 13:10 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Al-Khwarizmi escribió:
Simplemente se trata de hacer que el parseCommandOnContents llame al parseCommand. O sea, tú escribes el parseCommand con todo tu código complejo para la acción, y ese parseCommand sólo se ejecuta si el objeto no está dentro de ningún contenedor. Pero después, tú escribes el parseCommandOnContents, y no duplicas el código, sino que haces que llame al parseCommand. O sea, una línea:

Código:
void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
   parseCommand(aCreature,verb,args);
}



Creo que no me he explicado bien yo me refiero a que eso me obliga a hacer dos capturas del mismo verbo una en cada parserCommand. ¿no?
De todos modos en el ejemplo que has puesto de la rosa, hay dos parserCommands, el original y el OnContents.
El primero captura el verbo oler de la forma habitual, el segundo lo captura también pero con una sintaxis totalmente distinta, utilizando una variable llamada "message".
No veo que desde el OnContents se llame al original. ¿Podrías poner un ejemplo de lo que dices?

Citar:
De todas formas, si no te gusta esto, puedo hacer que el parseCommandOnContents funcione con todos los objetos, estén en un contenedor o no. De esta manera para hacer una acción que se ejecute sobre cualquier objeto esté o no en un contenedor, simplemente invocarías el parseCommandOnContents (a cambio, sería algo más complicado hacer acciones que se ejecuten SÓLO sobre objetos que están en un contenedor, porque requeriría comprobar el path). ¿Esto te parecería mejor?


No sé si he entendido bien... ¿quieres decir olvidarme del parsecommand original y capturar todas las acciones con el parsercommandOnContents?

O sea, cambiar el simple
Código:
 aCreature.write("Hmm. Huele bien, la rosa esta.\n");


de todos los objetos por

Código:
"   
       Item theDirectContainer = path.get(1);
      Item theOtherContainer = null;
      if ( path.size() > 2 ) theOtherContainer = path.get(2);
      String message = "Hmm. Huele bien, la rosa esta.\n";
      aCreature.write(message);


¿Podrías ponerme otro ejemplo, tanto como un objeto que esté dentro de un contenedor como de uno que no lo esté?
Es que creo que no termino de entenderte.
Muchas gracias.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 13 Jul 2009 14:17 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5312
Ubicación: Coruña
jenesis escribió:
Creo que no me he explicado bien yo me refiero a que eso me obliga a hacer dos capturas del mismo verbo una en cada parserCommand. ¿no?
De todos modos en el ejemplo que has puesto de la rosa, hay dos parserCommands, el original y el OnContents.
El primero captura el verbo oler de la forma habitual, el segundo lo captura también pero con una sintaxis totalmente distinta, utilizando una variable llamada "message".
No veo que desde el OnContents se llame al original. ¿Podrías poner un ejemplo de lo que dices?


Es que el ejemplo que puse hace cosas distintas según si la rosa está dentro de un contenedor o no. No lo puse como intención de ser un ejemplo sencillo, sino para que se viese todo lo que se puede hacer con el parseCommandOnContents. Todas esas complicaciones con la variable message están ahí porque he puesto un código para que, según el contenedor en el que esté la rosa, se muestre un texto distinto (que muestra el nombre del contenedor, o incluso de dos si está dentro de uno que a su vez está dentro de otro).

Si tú simplemente quieres que la rosa se pueda oler, esté o no esté dentro de un contenedor, harías lo siguiente:

Código:
void parseCommand( Mobile aCreature , String verb , String args )
{
   if ( verb.equalsIgnoreCase("oler") )
   {
      aCreature.write("Hmm. Huele bien, la rosa esta.\n");
      end();
   }
}

void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
   parseCommand ( aCreature , verb , args );
}


O sea, el parseCommand es como siempre, y el parseCommandOnContents lo que hace es simplemente llamar al parseCommand, de forma que si la rosa está en un contenedor, se hará el mismo procesado que si no lo estuviera. No necesitas para nada todo eso de message ni de chequear el path, eso sólo lo necesitarías si quisieras acceder a los contenedores explícitamente como hice yo en el ejemplo.


Citar:
No sé si he entendido bien... ¿quieres decir olvidarme del parsecommand original y capturar todas las acciones con el parsercommandOnContents?


Sí, quiero decir que una posibilidad sería eso, para las acciones que quieras que se puedan ejecutar también sobre objetos que están en contenedores (las que no quieras que sean así se seguirían tratando con el parseCommand de toda la vida).

Citar:
O sea, cambiar el simple
Código:
 aCreature.write("Hmm. Huele bien, la rosa esta.\n");


de todos los objetos por

Código:
"   
       Item theDirectContainer = path.get(1);
      Item theOtherContainer = null;
      if ( path.size() > 2 ) theOtherContainer = path.get(2);
      String message = "Hmm. Huele bien, la rosa esta.\n";
      aCreature.write(message);


No, porque como he dicho ese segundo código es más complicado porque hace más cosas, no sólo hacer que "oler" se pueda ejecutar dentro de un contenedor. Este cambio que te digo yo no implicaría más complejidad si lo único que quieres hacer es que la acción pueda ejecutarse dentro de un contenedor.

jenesis escribió:
¿Podrías ponerme otro ejemplo, tanto como un objeto que esté dentro de un contenedor como de uno que no lo esté?
Es que creo que no termino de entenderte.
Muchas gracias.


Tal como lo tenemos ahora, sería así:

* Para que la acción se pueda ejecutar siempre, tanto si el objeto está en un contenedor como si no (lo que tú quieres hacer en este caso, creo):

Código:
void parseCommand( Mobile aCreature , String verb , String args )
{
   if ( verb.equalsIgnoreCase("oler") )
   {
      aCreature.write("Hmm. Huele bien, la rosa esta.\n");
      end();
   }
}

void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
   parseCommand ( aCreature , verb , args );
}


* Para que sólo se pueda ejecutar si el objeto no está en un contenedor:

Código:
void parseCommand( Mobile aCreature , String verb , String args )
{
   if ( verb.equalsIgnoreCase("oler") )
   {
      aCreature.write("Hmm. Huele bien, la rosa esta.\n");
      end();
   }
}


Para que sólo se pueda ejecutar si sí está en un contenedor:

Código:
void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
    if ( verb.equalsIgnoreCase("oler") )
   {
      aCreature.write("Hmm. Huele bien, la rosa esta.\n");
      end();
   }
}


Con el cambio que he dicho que se podría hacer, quedaría así:

* Para que se ejecute siempre, tanto si está en un contenedor como si no (lo que tú quieres hacer en este caso, creo):

Código:
void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
    if ( verb.equalsIgnoreCase("oler") )
   {
      aCreature.write("Hmm. Huele bien, la rosa esta.\n");
      end();
   }
}


* Para que sólo se pueda ejecutar si no está en un contenedor:

Código:
void parseCommand( Mobile aCreature , String verb , String args )
{
   if ( verb.equalsIgnoreCase("oler") )
   {
      aCreature.write("Hmm. Huele bien, la rosa esta.\n");
      end();
   }
}


* Para que sólo se pueda ejecutar si sí está en un contenedor:

Código:
void parseCommandOnContents( Mobile aCreature , String verb , String args , List path )
{
    if ( verb.equalsIgnoreCase("oler") && path.size() < 1 )
   {
      aCreature.write("Hmm. Huele bien, la rosa esta.\n");
      end();
   }
}


Estoy pensando y creo que puede merecer la pena el cambio, hace la cosa un poco más sencilla para acciones como la que quieres tú; y sobre todo la hará más sencilla para casos donde tengas dos objetos, uno esté en un contenedor y el otro no. (no tiene mucho sentido que haya métodos para cada caso concreto, parece más cómodo que el onContents sea capaz de tratarte todos los casos donde potencialmente pueda haber contenedores).

_________________
Actúa siempre de tal modo que las decisiones de tu voluntad pudiesen servir como preceptos de una legislación universal (E. Kant)


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 13 Jul 2009 14:32 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Al-Khwarizmi escribió:
Es que el ejemplo que puse hace cosas distintas según si la rosa está dentro de un contenedor o no. No lo puse como intención de ser un ejemplo sencillo, sino para que se viese todo lo que se puede hacer con el parseCommandOnContents. Todas esas complicaciones con la variable message están ahí porque he puesto un código para que, según el contenedor en el que esté la rosa, se muestre un texto distinto (que muestra el nombre del contenedor, o incluso de dos si está dentro de uno que a su vez está dentro de otro).


Pues hijo mío, no me des esos sustos porque yo ya me estaba mareando con tanto message. xDDD
A mí primero me lo expones en plan sencillo y sin complicaciones que para enrevesarlo siempre hay tiempo. :lol:

La verdad es que no sé cuál de los dos modos es más práctico, pero dado que ya lo has hecho, casi mejor déjalo tal cual está ahora.
Me llevo los ejemplos y la explicación a mi archivo de apuntes. :)
Y dado que este hilo ha terminado en un tema mucho más selectivo de lo que era en un principio, voy a editar el primer mensaje y ponerle el nombre del nuevo parserCommand.

Muchas gracias


Arriba
 Perfil  
 
Mostrar mensajes previos:  Ordenar por  
Nuevo tema Responder al tema  [ 11 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 3 invitados


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