CAAD

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

Todos los horarios son UTC + 1 hora




Nuevo tema Responder al tema  [ 10 mensajes ] 
Autor Mensaje
NotaPublicado: 15 Sep 2009 20:41 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5312
Ubicación: Coruña
Bueno, antes de mandarte el release de AGE+PUCK que contiene todos los parseCommands, voy a dejar aquí puesto lo que hacen. Tal vez sea lo más próximo a documentación que me veáis hacer :P

Tenemos dos tipos de parseCommands:

A. Los que se refieren sólo a acciones sobre objetos que están en el, llamémosle, alcance directo del jugador (es decir, no están contenidos en nada, sino que están directamente en la habitación donde está el jugador, o en el inventario del mismo).
B. Los que se refieren a acciones sobre objetos que están en el, llamémosle, alcance indirecto del jugador (es decir, que o están en la habitación, o en el inventario del jugador, o contenidos en objetos que están en alguno de estos sitios, directamente o a través de otros contenedores). Estos parseCommands del tipo B se pueden usar para dos cosas: o bien para controlar directamente las acciones sobre estos objetos (al estilo de los del tipo A), o bien para que un contenedor pueda interceptar acciones sobre objetos que están dentro de él. Los parseCommands de este tipo B se identifican porque contienen en su nombre "onContents".

Dentro de cada tipo tenemos los siguientes subtipos:
1. El parseCommand para un solo objeto, llamado parseCommand[onContents]. Captura acciones sobre un solo objeto, como "coger la espada".
2. Los parseCommand para dos objetos con orden, llamados parseCommand[onContents]Obj1 y parseCommand[onContents]Obj2. Capturan acciones sobre dos objetos en un orden determinado, como por ejemplo "romper la puerta con la espada". El parseCommand[onContents]Obj1 se pone en el primer objeto, y nos da como parámetro el segundo. El parseCommand[onContents]Obj2 se pone en el segundo, y nos da como parámetro el primero. (nótese que sólo hace falta definir uno de ellos para definir la acción, pero que haya dos vale para que la podamos definir desde cualquiera de los dos objetos).
3. Los parseCommand para dos objetos reversibles, llamados parseCommand[onContents]TwoObjects. Capturan acciones sobre dos objetos en cualquier orden. Por ejemplo, el mismo método se podría usar para capturar "atar la piedra a la tabla" y "atar la tabla a la piedra". Si lo definimos en la piedra, siempre nos dará como parámetro la tabla, y viceversa, de modo que no tenemos que preocuparnos del orden en que el jugador ha puesto los objetos.
4. Los parseCommand genéricos, llamados parseCommand[onContents]Generic. Éstos se pueden usar tanto para acciones sobre un objeto como sobre dos objetos, y con los objetos en cualquier orden. Se pueden definir sobre cualquiera de los objetos involuncrados en la acción (si es que son dos). Nos proporciona como parámetros los dos objetos en el orden en que los introdujo el jugador. Nótese que, como también se ejecutan si sólo ha introducido un objeto, en este último caso el segundo objeto parámetro valdrá null. Esto quiere decir que en estos casos hacer obj2.(...) provocaría una excepción, hay que chequear antes que obj2 != null para evitar un NullPointerException.

Los parseCommands del tipo B (onContents) siempre tienen uno o dos parámetros adicionales (según el número de objetos involucrados en la acción) que nos da el "camino de contenedores" desde el objeto al que se refería el jugador. Es decir, por ejemplo: si el jugador teclea "coger la perla" y la perla está dentro de un estuche que está dentro de un baúl, este parámetro tomará como valor un vector cuyos elementos serán [objeto perla, objeto estuche, objeto baúl]. Así podemos hacer, por ejemplo, que un objeto se comporte distinto según dentro de qué está.

Nótese que los parseCommands del tipo B (onContents) tienen una doble utilidad: se pueden definir directamente sobre los objetos cuyas acciones se quiere modificar (por ejemplo, si queremos que al coger la perla el jugador reciba una descarga eléctrica, definimos el parseCommand de la perla). Pero también se pueden definir sobre un contenedor para capturar las acciones sobre objetos que estén dentro de él. Por ejemplo, si definimos el parseCommand en el baúl, también capturará las acciones que vayan a la perla. Nótese que para distinguir una acción que va a la perla de una que va al baúl, se puede hacer mirando los vectores antes mencionados: para la acción que va a la perla será [perla, estuche, baúl], y para la que va al baúl será [baúl].

Aquí van las declaraciones:

A1.

Código:
/*Método de análisis sintáctico de la entrada referida a una cosa*/
void parseCommand( Mobile aCreature , String verb , String args )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "comer"
   //args: resto de la orden que introduce, por ejemplo "la seta"
   
   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}


A2a.
Código:
/*Método de análisis sintáctico de la entrada referida a dos cosas, que no están dentro de otras*/
/*Este método se ejecuta cuando el jugador invoca una orden sobre dos objetos, que no están en contenedores, y el primero de los cuales es éste.
*/
void parseCommandObj1 ( Mobile aCreature , String verb , String args1 , String args2 , Entity obj2  )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "afilar"
   //args1: parte de la orden que se refiere a un primer objeto (que es este objeto), por ejemplo "el cuchillo".
   //args2: parte de la orden que se refiere a un segundo objeto, por ejemplo "con el afilador"
   //obj2: segundo objeto al que se refiere la acción del jugador (en el ejemplo, el objeto afilador).

   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}


A2b.
Código:
/*Método de análisis sintáctico de la entrada referida a dos cosas, que no están dentro de otras*/
/*Este método se ejecuta cuando el jugador invoca una orden sobre dos objetos, que no están en contenedores, y el segundo de los cuales es éste.
*/
void parseCommandObj2 ( Mobile aCreature , String verb , String args1 , String args2 , Entity obj1  )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "afilar"
   //args1: parte de la orden que se refiere a un primer objeto, por ejemplo "el cuchillo".
   //args2: parte de la orden que se refiere a un segundo objeto (que es este objeto), por ejemplo "con el afilador"
   //obj2: primer objeto al que se refiere la acción del jugador (en el ejemplo, el objeto cuchillo).

   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}


A3.
Código:
/*Método de análisis sintáctico de la entrada referida a dos cosas, que no están dentro de otras*/
/*Este método se ejecuta cuando el jugador invoca una orden sobre dos objetos no contenidos en otros, uno cualquiera de los cuales es éste.
*/
void parseCommandTwoObjects ( Mobile aCreature , String verb , String args1 , String args2 ,  Entity otherEnt  )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "atar"
   //args1: parte de la orden que se refiere a este objeto, por ejemplo "la piedra".
   //args2: parte de la orden que se refiere al otro objeto, por ejemplo "a la tabla"
   //otherEnt: objeto al que se refiere la acción del jugador, aparte de éste (o del objeto contenido en éste).
      //si self es la piedra, otherEnt sería la tabla; si self es la tabla, otherEnt sería la piedra.
   
   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}


A4.
Código:
/*Método de análisis sintáctico de la entrada referida a una o dos cosas, que no están dentro de otras*/
/*Este método se ejecuta cuando el jugador invoca una orden sobre uno o dos objetos que no están dentro de un contenedor, uno de los cuales es éste.
*/
void parseCommandGeneric ( Mobile aCreature , String verb , String args1 , String args2 , Entity obj1 , Entity obj2 ,  boolean goesFirst )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "afilar"
   //args1: parte de la orden que se refiere a un primer objeto, por ejemplo "el cuchillo"
   //args2: parte de la orden que se refiere a un segundo objeto, por ejemplo "con el afilador". La cadena vacía si no hay segundo objeto.
   //obj1: primer objeto al que se refiere la acción del jugador (en el ejemplo, el objeto cuchillo).
   //obj2: segundo objeto al que se refiere la acción del jugador (en el ejemplo, el objeto afilador). Valdrá null si no hay segundo objeto.
   //goesFirst: si vale true, es que el primer objeto (obj1) es éste (self) o está contenido en éste.
      //Si vale false, es que el segundo objeto (obj2) es éste (self) o está contenido en éste.
   
   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}


B1.
Código:
/*Método de análisis sintáctico de la entrada referida a una cosa, que puede estar contenida dentro de otra*/
/*Este método se ejecuta:
  - Cuando el jugador invoca una orden sobre este objeto (esté o no dentro de un contenedor).
  - Cuando este objeto es un contenedor, y el jugador invoca una orden sobre un objeto contenido en él.
      [en este caso, el objeto sobre el que invocó la orden se obtiene como ((Item)path.get(0))].
*/
void parseCommandOnContents ( Mobile aCreature , String verb , String args , Vector path )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "comer"
   //args: resto de la orden que introduce, por ejemplo "la seta"
   //path: camino de contenedores desde el objeto que introdujo el jugador. Por ejemplo, si introdujo "comer la seta" y la seta
   //   está en una caja, este vector será [seta, caja]. Si la caja está a su vez dentro de un baúl, [seta, caja, baúl]
   
   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}


B2a.
Código:
/*Método de análisis sintáctico de la entrada referida a dos cosas, que pueden o no estar dentro de otras*/
/*Este método se ejecuta:
  - Cuando el jugador invoca una orden sobre dos objetos, el primero de los cuales es éste (estén o no estos objetos dentro de un contenedor).
  - Cuando el jugador invoca una orden sobre dos objetos, el primero de los cuales está contenido en éste.
*/
void parseCommandOnContentsObj1 ( Mobile aCreature , String verb , String args1 , String args2 , Vector path1 , Vector path2 ,  Entity obj2  )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "afilar"
   //args1: parte de la orden que se refiere a un primer objeto, por ejemplo "el cuchillo". Ese primer objeto es éste o está contenido
      //en éste.
   //args2: parte de la orden que se refiere a un segundo objeto, por ejemplo "con el afilador"
   //path1: camino de contenedores desde el primer objeto al que referencia la orden. Por ejemplo, si introdujo "afilar el cuchillo con el
      //afilador" y el cuchillo está en una caja, será [cuchillo, caja].
   //path2: camino de contenedores desde el segundo objeto al que referencia la orden. Por ejemplo, si introdujo "afilar el cuchillo con el
      //afilador" y el afilador no está dentro de nada, será [afilador].
   //obj2: segundo objeto al que se refiere la acción del jugador (en el ejemplo, el objeto afilador).
   
   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}


B2b.
Código:
/*Método de análisis sintáctico de la entrada referida a dos cosas, que pueden o no estar dentro de otras*/
/*Este método se ejecuta:
  - Cuando el jugador invoca una orden sobre dos objetos, el segundo de los cuales es éste (estén o no estos objetos dentro de un contenedor).
  - Cuando el jugador invoca una orden sobre dos objetos, el segundo de los cuales está contenido en éste.
*/
void parseCommandOnContentsObj2 ( Mobile aCreature , String verb , String args1 , String args2 , Vector path1 , Vector path2 ,  Entity obj1  )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "afilar"
   //args1: parte de la orden que se refiere a un primer objeto, por ejemplo "el cuchillo".    
   //args2: parte de la orden que se refiere a un segundo objeto, por ejemplo "con el afilador". Ese segundo objeto
      //es éste o está contenido en éste.
   //path1: camino de contenedores desde el primer objeto al que referencia la orden. Por ejemplo, si introdujo "afilar el cuchillo con el
      //afilador" y el cuchillo está en una caja, será [cuchillo, caja].
   //path2: camino de contenedores desde el segundo objeto al que referencia la orden. Por ejemplo, si introdujo "afilar el cuchillo con el
      //afilador" y el afilador no está dentro de nada, será [afilador].
   //obj1: primer objeto al que se refiere la acción del jugador (en el ejemplo, el objeto cuchillo).
   
   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}


B3.
Código:
/*Método de análisis sintáctico de la entrada referida a dos cosas, que pueden o no estar dentro de otras*/
/*Este método se ejecuta:
  - Cuando el jugador invoca una orden sobre dos objetos, uno cualquiera de los cuales es éste (estén o no estos objetos dentro de un contenedor).
  - Cuando el jugador invoca una orden sobre dos objetos, uno cualquiera de los cuales está contenido en éste.
*/
void parseCommandOnContentsTwoObjects ( Mobile aCreature , String verb , String args1 , String args2 , Vector path1 , Vector path2 ,  Entity otherEnt  )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "atar"
   //args1: parte de la orden que se refiere a este objeto o a uno contenido en éste, por ejemplo "la piedra".
   //args2: parte de la orden que se refiere al otro objeto (o a uno contenido en otro), por ejemplo "a la tabla".
   //path1: camino de contenedores desde el objeto referenciado en args1. Por ejemplo, si introdujo "atar la piedra a la tabla"
      //y la piedra está en una caja, será [piedra, caja].
   //path2: camino de contenedores desde el otro objeto al que referencia la orden. Por ejemplo, si introdujo "atar la piedra a la tabla"
      //y la tabla no está dentro de nada, será [tabla].
   //obj2: objeto al que se refiere la acción del jugador, aparte de éste (o del objeto contenido en éste).
      //si self es la piedra, obj2 sería la tabla; si self es la tabla, obj2 sería la piedra.
   
   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}


B4.
Código:
/*Método de análisis sintáctico de la entrada referida a una o dos cosas, que pueden o no estar dentro de otras*/
/*Este método se ejecuta:
  - Cuando el jugador invoca una orden sobre uno o dos objetos, uno de los cuales es éste (estén o no estos objetos dentro de un contenedor).
  - Cuando el jugador invoca una orden sobre uno o dos objetos, uno de los cuales está contenido en éste.
*/
void parseCommandOnContentsGeneric ( Mobile aCreature , String verb , String args1 , String args2 , Vector path1 , Vector path2 , Entity obj1 , Entity obj2 ,  boolean goesFirst )
{
   
   //aCreature: criatura que introduce un comando.
   //verb: comando que introduce, por ejemplo "afilar"
   //args1: parte de la orden que se refiere a un primer objeto, por ejemplo "el cuchillo"
   //args2: parte de la orden que se refiere a un segundo objeto, por ejemplo "con el afilador"
   //path1: camino de contenedores desde el primer objeto al que referencia la orden. Por ejemplo, si introdujo "afilar el cuchillo con el
      //afilador" y el cuchillo está en una caja, será [cuchillo, caja].
   //path2: camino de contenedores desde el segundo objeto al que referencia la orden. Por ejemplo, si introdujo "afilar el cuchillo con el
      //afilador" y el afilador no está dentro de nada, será [afilador]. Valdrá null si no hay segundo objeto.
   //obj1: primer objeto al que se refiere la acción del jugador (en el ejemplo, el objeto cuchillo).
   //obj2: segundo objeto al que se refiere la acción del jugador (en el ejemplo, el objeto afilador). Valdrá null si no hay segundo objeto.
   //goesFirst: si vale true, es que el primer objeto (obj1) es éste (self) o está contenido en éste.
      //Si vale false, es que el segundo objeto (obj2) es éste (self) o está contenido en éste.
   
   
   //terminar con end(): interceptamos la frase, no se ejecuta lo que se tenga que ejecutar
   //por defecto ante ella
   //terminar normal: después de nuestro procesado, se lleva a cabo el análisis normal del
   //comando y ejecución de la acción correspondiente
   
}

_________________
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: 16 Sep 2009 12:11 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Genial!
Me quedo con el más completo que ahora mismo estoy probando y que parece que va bien. :D

Está el "problema" que me comentabas ayer, ahora mismo tenía a modo de comprobación un write que me comprobaba los valores de las variables y claro al pedir que imprimiera un valor que era null, ha saltado la alarma, imagino que era a eso a lo que te referías.

Target exception: java.lang.NullPointerException: Null Pointer in Method Invocation

Tendré que repasar todos los writes de control que tengo en el código, para no darme tales sustos. xD

De paso haré el cambio al nuevo método, y si no falla en ninguno creo que servirá como testeo definitivo.

Un saludo
Jenesis


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 16 Sep 2009 12:35 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5312
Ubicación: Coruña
jenesis escribió:
Está el "problema" que me comentabas ayer, ahora mismo tenía a modo de comprobación un write que me comprobaba los valores de las variables y claro al pedir que imprimiera un valor que era null, ha saltado la alarma, imagino que era a eso a lo que te referías.

Target exception: java.lang.NullPointerException: Null Pointer in Method Invocation


Sí, efectivamente, es eso. Siempre que te salga NullPointerException quiere decir que has intentado acceder a un objeto que es nulo.

De todas formas, en el caso de imprimir, puedes arreglarlo de forma que no tengas que hacer comprobaciones. Supongo que ahora tendrás algo como

write(objeto);

donde el objeto es nulo. Eso va a fallar. Pero si pones por ejemplo:

write("El objeto es: " + objeto);

Eso va a funcionar, si el objeto es nulo te pondrá: "El objeto es: null".

Concatenar con una cadena es de las poquitas cosas que se puede hacer con un nulo, además de compararlo con == o !=. Para otras cosas, siempre comprobar antes, ya sabes.

La verdad es que si tienes interés en escribir valores que sean null sin concatenar, también puedo retocar el método que escribe para que pueda hacerlo. De hecho, lo voy a hacer, no se pierde nada con ello.

Me alegro de que la cosa esté funcionando bien. :)

_________________
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: 16 Sep 2009 12:46 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Al-Khwarizmi escribió:
De todas formas, en el caso de imprimir, puedes arreglarlo de forma que no tengas que hacer comprobaciones. Supongo que ahora tendrás algo como

write(objeto);

donde el objeto es nulo. Eso va a fallar. Pero si pones por ejemplo:

write("El objeto es: " + objeto);

Eso va a funcionar, si el objeto es nulo te pondrá: "El objeto es: null".

Concatenar con una cadena es de las poquitas cosas que se puede hacer con un nulo, además de compararlo con == o !=. Para otras cosas, siempre comprobar antes, ya sabes.



Hnmmm, no sé...
El código que da el error es el siguiente:

aPlayer.write("\nverbo_espada " + verb + "\nargs1 " + args1 + "\nargs2 "+ args2 + "\nobj1 " + obj1 + "\n" + "\nobj2 " + obj2 + "\n"+ "\ngoesFirst " + goesFirst + "\n" );



Citar:
La verdad es que si tienes interés en escribir valores que sean null sin concatenar, también puedo retocar el método que escribe para que pueda hacerlo. De hecho, lo voy a hacer, no se pierde nada con ello.


Jo, ya sería la repanocha!!! :)
Aunque creo que el código que te he puesto es concatenado ¿no?


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 16 Sep 2009 12:53 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5312
Ubicación: Coruña
jenesis escribió:
Aunque creo que el código que te he puesto es concatenado ¿no?


Oh, pues sí, entonces es raro. Yo creo que esa línea no debería fallar. Mira a ver si no va a estar el fallo en otro lado (prueba a comentar ese write, y a ver si sigue fallando); o bien mándame el código del método completo del método y busco yo a ver, no vaya a ser que sea bug mío al ser el parseCommand nuevo del trinque...

_________________
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: 16 Sep 2009 13:39 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Al-Khwarizmi escribió:
jenesis escribió:
Aunque creo que el código que te he puesto es concatenado ¿no?


Oh, pues sí, entonces es raro. Yo creo que esa línea no debería fallar. Mira a ver si no va a estar el fallo en otro lado (prueba a comentar ese write, y a ver si sigue fallando); o bien mándame el código del método completo del método y busco yo a ver, no vaya a ser que sea bug mío al ser el parseCommand nuevo del trinque...


Si lo comento no da el error, pero aún así hay problemas, me acabo de dar cuenta que si intento usar un objeto con otro no existente o mal deletrado ocurre lo siguiente:

Código:
COMANDO>>  mete espada en lalala
bsh.TargetError found at parseCommandOnContentsGeneric(), command was ponerespada en lalala, entity number [ eu.irreality.age.Item:30000052:la espada], second object was null, error was Sourced file: inline evaluation of: ``parseCommandOnContentsGeneric( arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, a . . . '' : at Line: 6 : in file: /home/jenesis/AGE/mi_aventura/calabozo_espada.bsh : obj2 .equals ( world .getItem ( "barril" ) )

Called from method: parseCommandOnContentsGeneric : at Line: 1 : in file: inline evaluation of: ``parseCommandOnContentsGeneric( arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, a . . . '' : parseCommandOnContentsGeneric ( arg0 , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 , arg7 , arg8 )
Target exception: java.lang.NullPointerException: Null Pointer in Method Invocation
¿Cómo? ¿Poner qué dónde?


El barril que menciona está en el if del parseCommand de la espada, pero como ves no lo he mencionado en el comando, de hecho ni siquiera se cumple la condición, ya que el barril en ese momento no está en la misma localidad que la espada. y el juego ha sido reiniciado con lo que tampoco puede hacerse el listo pensando que hablo del barril.

if(verb.equalsIgnoreCase("poner") && obj2.equals(world.getItem("barril")))

Si no lo tienes claro te mando el código completo, ya me dirás.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 16 Sep 2009 13:47 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5312
Ubicación: Coruña
Sí, viendo eso lo veo claro...

El problema es lo de los nulos.

Si tú pones "poner espada en lalala", el parser del AGE detecta un solo objeto, que es la espada. Entonces, al parseCommand se le pasa ese objeto, y un nulo. Es decir, obj2 vale nulo.

Tú estás haciendo

obj2 .equals ( world .getItem ( "barril" ) )

(si te fijas sale en el mensaje de error)

Y como dije, no puedes hacer nada que sea obj2.algo() si el obj2 es nulo. En este caso el algo() es la llamada al método equals.

Así pues, tendrías que hacer:

Citar:
if ( obj2 != null )
{
if ( obj2.equals( world.getItem("barril") ) )
{
...
}
}


Por eso te digo que hay que tener cuidado con estas cosas al usar este parseCommand.

Por cierto que también vale

Citar:
if ( obj2 != null && obj2.equals( world.getItem("barril") ) )


por la evaluación en cortocircuito del and, no sé si lo has visto en algún otro lenguaje; pero cuando hay un and, si la primera condición es falsa ya no miras la segunda; con lo cual no llegarías a ejecutar el obj2.equals(...) si el objeto es nulo.

Y en este caso también te vale el "truco" de invertir el orden de lo que comparas, es decir, poner

Citar:
world.getItem("barril").equals(obj2)


porque sabes que world.getItem("barril") es seguro que no va a ser null, así que sobre él sí que puedes invocar el método equals. Pero bueno, esto último ya es un "truquillo", si quieres no liarte seguramente lo mejor te sea comprobar de una de las dos maneras anteriores. La del cortocircuito es cortita, y nunca te va a fallar.

Una de las cosas que tenía en la lista de cosas por hacer, y que ahora que ya están hechos los parseCommands coge prioridad, es hacer aquel equals de conveniencia. Ese equals va a ser de la forma equals(obj1,obj2) en vez de obj1.equals(obj2), y puedo hacer que trague los nulls. Aunque eso no te librará de tener que fijarte en los nulls para otras cosas que no sean comparar; es algo que por norma siempre hay que hacer en java (y en otros lenguajes) cuando tienes nulls.

_________________
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: 16 Sep 2009 14:07 
Desconectado
xyzzy

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

Una de las cosas que tenía en la lista de cosas por hacer, y que ahora que ya están hechos los parseCommands coge prioridad, es hacer aquel equals de conveniencia. Ese equals va a ser de la forma equals(obj1,obj2) en vez de obj1.equals(obj2), y puedo hacer que trague los nulls. Aunque eso no te librará de tener que fijarte en los nulls para otras cosas que no sean comparar; es algo que por norma siempre hay que hacer en java (y en otros lenguajes) cuando tienes nulls.


Bueno, por lo pronto lo he arreglado con el truquillo de cambiar el orden poniendo primero el item del mundo que sé que existe y luego comparándolo con el obj2, me ha parecido la forma más sencilla.
Creo que no voy a cambiar por ahora más parseCommands, al menos mientras sigas haciéndoles cambios, cuando tengas el nuevo me lo mandas y lo pruebo. :)


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 16 Sep 2009 14:09 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5312
Ubicación: Coruña
jenesis escribió:
Creo que no voy a cambiar por ahora más parseCommands, al menos mientras sigas haciéndoles cambios, cuando tengas el nuevo me lo mandas y lo pruebo. :)


No, si a los parseCommands no tengo planeado hacerles ningún cambio, a no ser que se descubra un bug. Por lo demás van a seguir igual.

Lo que te digo sobre hacer que el write soporte nulos, y un equals de conveniencia que también soporte nulos, son otros añadidos independientes de los parseCommands, que podrías usar en ellos o en cualquier otra parte de tu código, y que tampoco se va a cargar nada de lo ya existente (o sea, siempre se podrá seguir usando el equals de java).

_________________
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: 16 Sep 2009 14:13 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Al-Khwarizmi escribió:
jenesis escribió:
Creo que no voy a cambiar por ahora más parseCommands, al menos mientras sigas haciéndoles cambios, cuando tengas el nuevo me lo mandas y lo pruebo. :)


No, si a los parseCommands no tengo planeado hacerles ningún cambio, a no ser que se descubra un bug. Por lo demás van a seguir igual.

Lo que te digo sobre hacer que el write soporte nulos, y un equals de conveniencia que también soporte nulos, son otros añadidos independientes de los parseCommands, que podrías usar en ellos o en cualquier otra parte de tu código, y que tampoco se va a cargar nada de lo ya existente (o sea, siempre se podrá seguir usando el equals de java).


Ah vale, te había entendido mal. :)


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