Skip to content

Acciones y reacciones

Baltasar García Perez-Schofield edited this page Mar 22, 2015 · 2 revisions

Acciones y reacciones

Cuando el jugador teclea una orden, esta se traduce a una acción, con un objeto directo (el objeto sobre el que se realiza la acción) y, en ocasiones, un objeto indirecto (el objeto que ayuda a realizar la acción).

La estructura que lleva la orden del jugador, se llama parser.sentence o parser.sentencia. Esta estructura tiene lo siguientes miembros:

  • verb: El verbo de la acción.
  • term1: El objeto directo.
  • prep: La preposición.
  • term2: El objeto indirecto.

Así, si el jugador teclea, por poner un ejemplo:

> coge las zapatillas

Se almacenará en la estructura como:

  • verb: coge
  • term1: zapatillas
  • prep: null
  • term2: null
sentencia verb term1 prep term2
norte ir norte null null
coge las zapatillas coge zapatillas null null
abre la puerta con las herramientas abre puerta con herramientas

En la misma estructura, aparecen cuatro campos más, que se corresponden con la traducción de la orden a una acción que conozca la librería (si no la conoce, entonces ya se ha producido previamente un "no puedes hacer eso" o similar, fuera del alcance del autor). Estos campos son persona, act, obj1 y obj2. Para cuando el autor tiene el control de la acción, la traducción se ha producido ya.

sentencia verb term1 prep term2 persona act obj1 obj2
norte ir norte null null jugador Go null null
coge la zapatillas coge zapatillas null null jugador Take objZapatillas null
abre la puerta con las herramientas abre puerta con herramientas jugador Open objPuerta objHerramientas

Se puede encontrar en esta wiki un listado completo de acciones.

Una acción muy típica es tratar de coger algo, que en realidad no se puede tomar, o que se desea que aparezca un mensaje específico.

var objCactus = ctrl.creaObj( "cactus",
     [ "planta" ],
     "Un cactus lleno de espinas.",
     ctrl.lugares.limbo, Ent.Escenario
);

objCactus.preTake = function() {
    return "¡Que no, que me pincho!";
}

Efectivamente, la forma de manejarse con las acciones se basa en las funciones preXXX() y postXXX() donde XXX es el nombre de la acción. En el ejemplo anterior, la acción en concreto es take, y por tanto, la función a crear es preTake(). Si esta función existe, el resultado de la acción es aquello que devuelva ella, y no se continua. Las acciones de la librería contienen un método, doIt() que es el que se ejecuta cuando la acción es encontrada. Esta hace algunas comprobaciones además de la acción en sí, como comprobar si existe una función preXXX() en el objeto destino de la acción. En caso de que exista, se devuelve su valor de retorno; en caso contrario, se ejecuta el método exe(). Este método NO hace ninguna comprobación sobre preXXX(), se limita a cumplir con el trabajo de la acción. A veces este trabajo es real, como en el caso de take, en el que el objeto destino de la acción debe pasar a ser llevado por el personaje, mientras que en otros casos, el trabajo consiste únicamente en devolver un mensaje del estilo "no puedes hacer eso".

Una vez resuelta la elección entre exe() y preXXX(), la librería termina, en cualquier caso, llamando a postXXX(), siempre y cuando este exista, claro. El valor devuelto por este método se ignora, no tiene relación con lo que el jugador puede ver tras la acción.

var objCactus = ctrl.creaObj( "cactus",
     [ "planta" ],
     "Un cactus verde y amarillo.",
     ctrl.lugares.limbo, Ent.Escenario
);

objCactus.espinas = 5;

objCactus.preExamine = function() {
    var toret = objCactus.desc;

    if ( objCactus.espinas > 0 ) {
        toret += " Tiene " + objCactus.espinas + " espinas.";
    } else {
        toret += " Ya no tiene espinas.";
    }

    return toret;
}

objCactus.preTake = function() {
    var toret = "¡Me he pinchado! Por lo menos, ahora queda una espina menos...";

    if ( obj.espinas < 1 ) {
        acciones.getAccion( "take" ).exe( parser.sentencia, objCactus, ctr.personas.devJugador() );
        toret = "Ahora has podido coger el cactus.";
    }

    return toret;
}

objCactus.postTake = function() {
    objCactus.espinas -= 1;
}

En el código anterior, se toma ventaja del hecho de que las acciones se dividen en doIt() (con comprobaciones) y exe() sin comprobaciones, para tomar el cactus, en el caso de que el jugador ya se haya pinchado lo suficiente.

En ocasiones, es conveniente lanzar una acción distinta desde otra. Por ejemplo, abrir una puerta podría completarse metiendo la llave o abriendo la puerta.

var objLlave = ctrl.creaObj( "llave",
     [],
     "Pues sí, es una llave.",
     locCasa, Ent.Portable
);

var objPuerta = ctrl.creaObj( "puerta",
     [],
     "Pues sí, es una puerta.",
     locCasa, Ent.Escenario
);

objPuerta.ponAbierto( false );

objPuerta.preOpen = function() {
    var jugador = ctrl.personas.devJugador();
    var toret = "Necesitas algo para abrirla.";

    if ( !objPuerta.estaAbierto() ) {
        if( jugador.tiene( objLlave ) ) {
            toret = "Has abierto la puerta.";
            objPuerta.ponAbierto();
        }
    } else {
        toret = "Ya estaba abierta.";
    }

    return toret;
}

objLlave.preDrop = function() {
    var s = parser.sentencia;

    if ( s.obj2 === objPuerta ) {
        toret = acciones.ejecuta( "abre", "puerta" );
    } else {
        toret = acciones.devAccion( "drop" ).exe( s, objLlave );
    }

    return toret;
}

Todos los objetos controlan si están abiertos o cerrados, y por defecto, están abiertos. Los métodos isOpen()/estaAbierto() y ponAbierto() permiten gestionar esta condición.

Hay que tener en cuenta que "meter la llave en la puerta" se traduce como "dejar llave en la puerta", por lo que es necesario capturar la acción drop. Una vez hecho esto, en el caso de que obj2 sea la puerta, tenemos que abrirla. No tiene mucho sentido repetir aquí lo mismo que se hizo ya antes en objPuerta.preOpen() (repetir siempre es mala cosa), así que simplemente se lanza la acción "abre la puerta", mediante el método ejecuta(). Este método acepta hasta cuatro parámetros, que son cuatro cadenas que se corresponden con el verbo, el primer objeto, la preposición y el segundo objeto, y se encarga de rellenar la estructura y lanzar el parsing como si hubiera provenido del usuario. Nótese que esto mismo no se puede hacer en el caso else, es decir, cuando el obj2 no es la puerta. Si se tratara de hacer acciones.ejecuta( "deja", "llave" ); volvería a capturar la acción preDrop() terminando en un bucle infinito.

Clone this wiki locally