require("./../rur.js"); require("./../recorder/record_frame.js"); RUR.add_robot = function (robot) { var world = RUR.get_current_world(); if (world.robots === undefined){ world.robots = []; } if (robot === undefined) { robot = RUR.robot.create_robot(); } world.robots.push(robot); RUR.record_frame("RUR.add_robot", robot.__id); }; /** @function is_robot * @memberof RUR * @instance * @summary This function indicates if at least one robot is found at * the specified location, false otherwise. No error checking * is performed on the arguments. If some exception is raised, * it is simply logged in the browser's console. * * @param {integer} x Position * @param {integer} y Position * * @returns {bool} True if a robot is found at that position, false otherwise. * **/ RUR.is_robot = function (x, y) { "use strict"; var r, robot, world=RUR.get_current_world(); if (world.robots === undefined || world.robots.length === 0) { return false; } try { for (r=0; r<world.robots.length; r++) { robot = world.robots[r]; if (robot.x == x && robot.y == y){ return true; } } } catch(e) { console.warn("error in RUR.is_robot ", e); } return false; }; /** @function get_robot_body_by_id * * @memberof RUR * @instance * @summary **IMPORTANT** This function should only be used for the advanced * frame insertion technique. * * This function indicates returns a robot "body" specified by * its id, if a robot with such an id exists. (The `id` is * like a serial number: it is a number unique for each robot created). * No error checking is performed on the argument. If some exception is raised, * it is simply logged in the browser's console. * * **Important:** This function cannot be used directly in a Python program * to yield something sensible. (If you want, you can convert the result * to a Python dict() -- provided it is not None, of course.) * From Python, use instead `get_robot_by_id()` (without the RUR prefix), * or `robot_spécifique` in French, * which returns a true Python UsedRobot instance. * * @param {integer} id * * @returns {object} the body of the robot as a Javascript object, `null` if * a robot with this id cannot be found. * **/ RUR.get_robot_body_by_id = function (id) { "use strict"; var r, robot_body, world=RUR.get_current_world(); if (world.robots === undefined || world.robots.length === 0) { return null; } try { for (r=0; r<world.robots.length; r++) { robot_body = world.robots[r]; if (robot_body.__id == id){ return robot_body; } } } catch(e) { console.warn("error in RUR.get_robot_body_by_id ", e); } return null; }; /** @function get_robot_by_id * * @memberof RUR * @instance * @summary **IMPORTANT** This function should only be used for the advanced * frame insertion technique. * This function indicates returns a Javascript UsedRobot instance * specified by its id, if a robot with such an id exists. (The `id` is * like a serial number: it is a number unique for each robot created). * No error checking is performed on the argument. * If some exception is raised, it is simply logged in the browser's console. * * **Important:** This function cannot be used directly in a Python program * to yield something sensible. * From Python, use instead `get_robot_by_id()` (without the RUR prefix), * or `robot_spécifique` in French, * which returns a true Python UsedRobot instance. * * @param {integer} id * * @returns {object} A Javascript UsedRobot instance corresponding to the * robot with the specified id, or `null` if a robot with this id cannot be found. * **/ RUR.get_robot_by_id = function (id) { "use strict"; var body, robot; body = RUR.get_robot_body_by_id(id); if (body === null) { return null; } else { robot = Object.create(RUR.UsedRobot.prototype); robot.body = body; return robot; } }; /** @function get_robot_location * * @memberof RUR * @instance * @desc **IMPORTANT** This function should only be used for the advanced * frame insertion technique; in normal programs, used `position_here()`. * Use `import reeborg_en` followed by `help(reeborg_en.position_here())` * for details about the return values which are different from those of * `RUR.get_robot_location()`. * * This function returns the location of a robot (position **and** orientation). * * @param {object} robot_body A robot body object, having the proper attribute * for position (x, y coordinates) and orientation. Note that you should * pass in a robot body object obtained from some other function, * such as `RUR.get_robot_body_by_id()`, since * the internal names for the various attributes are subject to change. * * @returns {object} An object of the form * `{x:x_value, y:y_value, orientation:orientation_value} where * `x_value` and `y_value` are integers and * `orientation_value` is one of `"east"`, `"west"`, `"north"`, `"south"`. * **/ RUR.get_robot_location = function (robot_body) { "use strict"; var x, y, orientation; if (!robot_body || robot_body.x === undefined || robot_body.y === undefined || robot_body._orientation === undefined) { throw new Error("robot body needed as argument for RUR.get_location()."); } switch (robot_body._orientation){ case RUR.EAST: orientation = "east"; break; case RUR.NORTH: orientation = "north"; break; case RUR.WEST: orientation = "west"; break; case RUR.SOUTH: orientation = "south"; break; case RUR.RANDOM_ORIENTATION: throw new RUR.ReeborgError(RUR.translate("I am too dizzy!")); default: throw new Error("Should not happen: unhandled case in RUR.get_location()."); } return {x:robot_body.x, y:robot_body.y, orientation:orientation}; }; /** @function get_position_in_front * * @memberof RUR * @instance * @desc **IMPORTANT** This function should only be used for the advanced * frame insertion technique; in normal programs, used `position_in_front()`. * Use `import reeborg_en` followed by `help(reeborg_en.position_in_front())` * for details about the return values which are different from those of * `RUR.get_position_in_front()`. * * @param {object} robot_body A robot body object, having the proper attribute * for position (x, y coordinates) and orientation. Note that you should * pass in a robot body object obtained from some other function * such as `RUR.get_robot_body_by_id()`, since * the internal names for the various attributes are subject to change. * * @returns {object} An object of the form * `{x:x_value, y:y_value} where `x_value` and `y_value` are integers and * represent the position in front of the robot. If the position is not * within the world boundaries, the object `{x:0, y:0}` is returned. * **/ RUR.get_position_in_front = function (robot_body) { "use strict"; var x, y; if (!robot_body || robot_body.x === undefined || robot_body.y === undefined) { throw new Error("robot body needed as argument for RUR.get_position_in_front()."); } switch (robot_body._orientation){ case RUR.EAST: x = robot_body.x + 1; y = robot_body.y; break; case RUR.NORTH: y = robot_body.y + 1; x = robot_body.x; break; case RUR.WEST: x = robot_body.x - 1; y = robot_body.y; break; case RUR.SOUTH: y = robot_body.y - 1; x = robot_body.x; break; case RUR.RANDOM_ORIENTATION: throw new RUR.ReeborgError(RUR.translate("I am too dizzy!")); default: throw new Error("Missing _orientation attribute for robot_body in RUR.get_position_in_front()."); } if (RUR.is_valid_position(x, y)) { return {x:x, y:y}; } else { return {x:0, y:0}; } }; /** @function add_final_position * * @memberof RUR * @instance * @summary This function adds a final position as a goal for the default robot. * It is possible to call this function multiple times, with different * `x, y` positions; doing so will result in a final position chosen * randomly (among the choices recorded) each time a program is run. * * If `x, y` had previously been set as a goal final position * no change is being made and a message is logged in the browser's console. * * @param {string} name The name of the object/image we wish to use to * represent the final position of the robot. Only one * image can be used for a given world, even if many possible * choices exist for the final position: each time this * function is called, the `name` argument replaces any * such argument that was previously recorded. * * @param {integer} x The position on the grid * @param {integer} y The position on the grid * * @todo: put in argument verification code and note which error can be thrown * @throws Will throw an error if the final position is not valid [not implemented yet] * @throws will throw an error if the name is not recognized [not implemented yet] **/ RUR.add_final_position = function (name, x, y) { "use strict"; var goal, pos, world=RUR.get_current_world(); RUR.utils.ensure_key_for_obj_exists(world, "goal"); goal = world.goal; RUR.utils.ensure_key_for_obj_exists(goal, "position"); RUR.utils.ensure_key_for_array_exists(goal, "possible_final_positions"); for(var i=0; i<goal.possible_final_positions.length; i++) { pos = goal.possible_final_positions[i]; if(pos[0]==x && pos[1]==y){ console.log(x, y, ": this final position is already included!"); return; } } goal.position.x = x; goal.position.y = y; goal.position.image = name; goal.possible_final_positions.push([x, y]); RUR.record_frame("add_final_position", {name:name, x:x, y:y}); }; /** @function add_initial_position * * @memberof RUR * @instance * @summary This function adds an initial (starting) position as a possibility * for the default robot. It is possible to call this function multiple times, * with different `x, y` positions; doing so will result in a initial position * chosen randomly (among the choices recorded) each time a program is run. * * If `x, y` had previously been set as an initial position * no change is being made and a message is logged in the browser's console. * * @param {integer} x The position on the grid * @param {integer} y The position on the grid * * @todo: put in argument verification code and note which error can be thrown * @throws Will throw an error if the the world does not contain a robot * @throws Will throw an error if the initial position is not valid [not implemented yet] **/ RUR.add_initial_position = function (x, y) { "use strict"; var robot, pos, world=RUR.get_current_world(); if (world.robots === undefined || world.robots.length === 0) { throw new RUR.ReeborgError("This world has no robot; cannot set initial position."); } robot = world.robots[0]; if (!robot.possible_initial_positions){ robot.possible_initial_positions = [[robot.x, robot.y]]; } for(var i=0; i<robot.possible_initial_positions.length; i++) { pos = robot.possible_initial_positions[i]; if(pos[0]==x && pos[1]==y){ console.log(x, y, ": this initial position is already included!"); return; } } // in case we want to replace an existing initial position by adding // a new one, and then calling RUR.remove_initial_position, // we set the current initial position to the new one we just added. // This has no visible effect if more than one initial position is possible. robot._prev_x = robot.x = x; robot._prev_y = robot.y = y; robot.possible_initial_positions.push([x, y]); RUR.record_frame("add_initial_position", {x:x, y:y}); }; /** @function remove_initial_position * * @memberof RUR * @instance * @summary This function removes an initial (starting) position as a possibility * for the default robot. It is possible to call this function multiple times, * with different `x, y` positions. However, if there is only one remaining * initial position, such calls will be ignored to ensure that there is * always a robot present. * * If `x, y` is not an initial position * no change is being made and a message is logged in the browser's console. * * @param {integer} x The position on the grid * @param {integer} y The position on the grid * * @todo: put in argument verification code and note which error can be thrown * @throws Will throw an error if the the world does not contain a robot * @throws Will throw an error if the initial position is not valid [not implemented yet] **/ RUR.remove_initial_position = function (x, y) { "use strict"; var robot, pos, new_positions, world=RUR.get_current_world(); if (world.robots === undefined || world.robots.length === 0) { throw new RUR.ReeborgError("This world has no robot; cannot remove initial position."); } robot = world.robots[0]; if (!robot.possible_initial_positions){ robot.possible_initial_positions = [[robot.x, robot.y]]; return; } if (robot.possible_initial_positions.length == 1) { return; } new_positions = []; for(var i=0; i<robot.possible_initial_positions.length; i++) { pos = robot.possible_initial_positions[i]; if(pos[0]==x && pos[1]==y){ continue; } else { new_positions.push(pos); } } robot.possible_initial_positions = new_positions; RUR.record_frame("remove_initial_position", {x:x, y:y}); }; // TODO: try to set it in the middle of a program to have Reeborg being "dizzy". /** @function set_random_orientation * * @memberof RUR * @instance * @summary This function sets the initial (starting) orientation so that it * will be chosen randomly. * * @param {object} [robot_body] Optional robot body object * * @throws Will throw an error if it is called without an argument and * the world does not contain a robot. **/ RUR.set_random_orientation = function (robot_body) { "use strict"; var pos, world=RUR.get_current_world(); if (robot_body === undefined) { if (world.robots === undefined || world.robots.length < 1) { throw new RUR.ReeborgError("This world has no robot; cannot set random orientation."); } robot_body = world.robots[0]; } else if (robot_body.__id === undefined) { throw new RUR.ReeborgError("Invalid robot_body argument in RUR.set_random_orientation."); } robot_body._orientation = RUR.RANDOM_ORIENTATION; robot_body._prev_orientation = RUR.RANDOM_ORIENTATION; RUR.record_frame("set_random_orientation", robot_body.__id); };