1

I am playing Untrusted to teach myself JS, and I am curious how a certain function is evaluated.

The 'level' robotMaze gives you the following code to work on:

/*
 * robotMaze.js
 *
 * The blue key is inside a labyrinth, and extracting
 * it will not be easy.
 *
 * It's a good thing that you're a AI expert, or
 * we would have to leave empty-handed.
 */

function startLevel(map) {
    map.getRandomInt = function(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    map.placePlayer(map.getWidth()-1, map.getHeight()-1);
    var player = map.getPlayer();

    map.defineObject('robot', {
        'type': 'dynamic',
        'symbol': 'R',
        'color': 'gray',
        'onCollision': function (player, me) {
            me.giveItemTo(player, 'blueKey');
        },

and right here is where the player is allowed to modify code, which controls a single moving object in a maze.

        'behavior': function (me) {
            // move randomly
            var moves = map.getAdjacentEmptyCells(me.getX(), me.getY());
            // getAdjacentEmptyCells gives array of ((x, y), direction) pairs
            me.move(moves[map.getRandomInt(0, moves.length - 1)][1]);



        }
    });

The rest of the code is only run once as far as I can tell to set up the board at the start.

    map.defineObject('barrier', {
        'symbol': '░',
        'color': 'purple',
        'impassable': true,
        'passableFor': ['robot']
    });

    map.placeObject(0, map.getHeight() - 1, 'exit');
    map.placeObject(1, 1, 'robot');
    map.placeObject(map.getWidth() - 2, 8, 'blueKey');
    map.placeObject(map.getWidth() - 2, 9, 'barrier');

    var autoGeneratedMaze = new ROT.Map.DividedMaze(map.getWidth(), 10);
    autoGeneratedMaze.create( function (x, y, mapValue) {
        // don't write maze over robot or barrier
        if ((x == 1 && y == 1) || (x == map.getWidth() - 2 && y >= 8)) {
            return 0;
        } else if (mapValue === 1) { //0 is empty space 1 is wall
            map.placeObject(x,y, 'block');
        } else {
            map.placeObject(x,y,'empty');
        }
    });
}

My question is, if I store or access values in variables or from inside the map.defineObject's 'behavior' property, in what scope are they evaluated, and how persistent are they? For example, I might want to make a dumb maze solver that always makes right turns; for that I need to define an orientation variable.

Testing shows that there is some kind of persistence, but I would like to know the formal answer just in case (rather than implicitly from a game).

bright-star
  • 6,016
  • 6
  • 42
  • 81

1 Answers1

1

The answer will depend on how/where the variables are declared, which variables you are trying to access and how the scope is set for the behavior function. A more detailed discussion is in this SO, but in your example:

  1. The moves variable has local scope in the function, it will be destroyed when the function finishes executing;
  2. If you modify the me parameter, it will survive the function exit, because it is passed as a reference;
  3. Based on the snippets of code you posted, the map variable is global or is defined in an enclosing scope that contains the behavior function, so if you modify its data, those changes will also survive the function exit.
Community
  • 1
  • 1
rfernandes
  • 1,121
  • 7
  • 9
  • In other words, if 3. is true in the scope of `map`, 1. will not apply? – bright-star Apr 14 '14 at 05:59
  • 1
    For example, if `map` is declared an a global scope (ie outside of all objects) then if you modify one of its existing members inside `behavior`, then that member will continue to hold that value after you leave the function. – rfernandes Apr 14 '14 at 06:05