<commit_before>function createUi() {
    return new SimpleUi();
}

function createDefaultLevel(ui) {

    var points = [
        [0, 0],
        [1, 0],
        [1, 1],
        [1, 2],
        [2, 2],
        [3, 2],
        [3, 3],
        [3, 4],
        [4, 4],
        [5, 4],
        [5, 3],
        [5, 2],
        [6, 2],
        [7, 2],
        [8, 2],
        [9, 2]
    ];

	var nodes = generateNodes(points);  
	var map = new Map(nodes, ui);
	var van = new Van(nodes[0], nodes[1], ui);
	return new Level(map, van, nodes[nodes.length - 1], ui);
}

function generateNodes(points){
	var previousNode = null;
	var nodes = [];
	for (var i = 0; i < points.length; i++) {
	      var p = points[i];
	      var coordinate = new Coordinate(p[0], p[1]);
	      var node = new Node(coordinate);
	      if (previousNode) {
	          node.addConnectedNodeWithBacklink(previousNode);
	      }
	      previousNode = node;
	      nodes.push(node);
	}
	return nodes;
}

/**
  * Generates a random road given a starting point and seed from the range <0, 1>, 
  * where 1 creates a completely straight road and 0 does not influence the way 
  * the next road element is chosen at all.
  */
function generateRandomPathPoints(current, seed) {
	var points = [];
	var visited = initialiseVisited();
	var possibleNext = null;
	var orientation = current[1] == 0 ? -1 : 2;
	var possibleStaight = null;

	points.push(current);
	visited[current[0]][current[1]] = true;
	current = getNextBasedOnOrientation(current, orientation);

	while (!isOutOfBounds(current)) {
		
		visited[current[0]][current[1]] = true;
		possibleNext = getPossibleNextMoves(current, visited);
		possibleStraight = getNextBasedOnOrientation(current, orientation);
		
		if (Math.random() < seed && possibleStraight != -1 
			&& isFree(possibleStraight, visited)) {
			points.push(current);
			current = possibleStraight;
			console.debug(current);

		} else {

			if (possibleNext.length == 0) {
				if(isOnBorder(current)) {
					points.push(current);
					return points;
				}
				current = points.pop();

			} else {

				var decision = Math.floor((Math.random() * possibleNext.length));
				points.push(current);
				next = possibleNext[decision];
				orientation =  (2 * (next[0] - current[0]) + (next[1] - current[1]));
				current = possibleNext[decision];
			}
		}
	}
	console.debug("blah");
	for (var i = 0; i < points.length; i++) {
		console.debug(points[i]);
	}
	console.debug("blah2");
	return points;

	/*						*(1, 0) 1
	 *		
	 *      *(-1,0) -2     	x(0, 0)      	*(1, 0) 2
	 *
	 *						*(-1, 0) -1
	 *
	 * Returns next point in the same orientation or -1 if it would go out of bounds. 
	 */					
	function getNextBasedOnOrientation(point, orientation) {
		var result = null;
		switch(orientation) {
			case 1:
				result = [point[0], point[1] + 1];
				break;
			case -1:
				result = [point[0], point[1] - 1];
				break;
			case 2:
				result = [point[0] + 1, point[1]];
				break;
			case -2:
				result = [point[0] - 1, point[1]];
				break;
		}
		return isOutOfBounds(result) ? -1 : result;
	}

	function isOutOfBounds(point) {
		return point[0] < 0 || point[0] >= GRID_WIDTH || point[1] < 0 || point[1] >= GRID_HEIGHT;
	}

	function isOnBorder(point) {
		return point[0] == 0 || point[0] == GRID_WIDTH || point[1] == 0 || point[1] == GRID_HEIGHT;
	}

	function isFree(point, visited) {
		return !visited[point[0]][point[1]];
	}

	function getPossibleNextMoves(point, visited) {
		var possible = [];
		var possiblePoint = null;
		var considered = [[point[0], point[1] + 1], [point[0] + 1, point[1]], 
			[point[0] - 1, point[1]], [point[0], point[1] - 1]];
		for (var i= 0; i < 4; i++) {
			possiblePoint = considered[i];
			if(!isOutOfBounds(possiblePoint) && isFree(possiblePoint, visited)) {
				possible.push(possiblePoint);
			}
		}
		return possible;
	}

	function initialiseVisited() {
		var visited = new Array(GRID_WIDTH);
		for (var i = 0; i < GRID_WIDTH; i++) {
			visited[i] = new Array(GRID_HEIGHT);
		}
		return visited;
	}
}

function defaultProgram(level) {
	  var program = new Program(
	          [TURN_LEFT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_LEFT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_LEFT,
	              FORWARD,
	              FORWARD,
	              FORWARD
	          ]);
	
	  level.play(program);
}

function trackDevelopment(level) {
	var program = new Program([]);
	
	$('#moveForward').click(function() {
		program.instructions.push(FORWARD);
    });
	
    $('#turnLeft').click(function() {
    	program.instructions.push(TURN_LEFT);
    });

    $('#turnRight').click(function() {
		program.instructions.push(TURN_RIGHT);
	});
    
    $('#play').click(function() {
    	level.play(program);
	});

	$('#randomRoad').click(function() {
		var ui = createUi();
		var points = generateRandomPathPoints([0,4], 0);
		var nodes = generateNodes(points);  
		var van = new Van(nodes[0], nodes[1], ui);
		var map = new Map(nodes, ui);
	})<commit_msg>Added the length parameter. Will probably be useful for simple levels together with the high seed.<commit_after>function createUi() {
    return new SimpleUi();
}

function createDefaultLevel(ui) {

    var points = [
        [0, 0],
        [1, 0],
        [1, 1],
        [1, 2],
        [2, 2],
        [3, 2],
        [3, 3],
        [3, 4],
        [4, 4],
        [5, 4],
        [5, 3],
        [5, 2],
        [6, 2],
        [7, 2],
        [8, 2],
        [9, 2]
    ];

	var nodes = generateNodes(points);  
	var map = new Map(nodes, ui);
	var van = new Van(nodes[0], nodes[1], ui);
	return new Level(map, van, nodes[nodes.length - 1], ui);
}

function generateNodes(points){
	var previousNode = null;
	var nodes = [];
	for (var i = 0; i < points.length; i++) {
	      var p = points[i];
	      var coordinate = new Coordinate(p[0], p[1]);
	      var node = new Node(coordinate);
	      if (previousNode) {
	          node.addConnectedNodeWithBacklink(previousNode);
	      }
	      previousNode = node;
	      nodes.push(node);
	}
	return nodes;
}

/**
  * Generates a random road given a starting point and seed and length.
  * Seed - a number from the range <0, 1>, where 1 creates a completely straight road
  * and 0 does not influence the way the next road element is chosen at all.
  * Length - optional argument limiting the length of the path.
  */
function generateRandomPathPoints(current, seed, length) {
	var points = [];
	var visited = initialiseVisited();
	var possibleNext = null;
	var orientation = current[1] == 0 ? -1 : 2;
	var possibleStaight = null;
	length = length == undefined ? Number.POSITIVE_INFINITY : length;

	points.push(current);
	visited[current[0]][current[1]] = true;
	current = getNextBasedOnOrientation(current, orientation);

	while (!isOutOfBounds(current) && points.length < length) {
		
		visited[current[0]][current[1]] = true;
		possibleNext = getPossibleNextMoves(current, visited);
		possibleStraight = getNextBasedOnOrientation(current, orientation);
		
		if (Math.random() < seed && possibleStraight != -1 
			&& isFree(possibleStraight, visited)) {
			points.push(current);
			current = possibleStraight;
			console.debug(current);

		} else {

			if (possibleNext.length == 0) {
				if(isOnBorder(current)) {
					points.push(current);
					return points;
				}
				current = points.pop();

			} else {

				var decision = Math.floor((Math.random() * possibleNext.length));
				points.push(current);
				next = possibleNext[decision];
				orientation =  (2 * (next[0] - current[0]) + (next[1] - current[1]));
				current = possibleNext[decision];
			}
		}
	}
	console.debug("blah");
	for (var i = 0; i < points.length; i++) {
		console.debug(points[i]);
	}
	console.debug("blah2");
	return points;

	/*						*(1, 0) 1
	 *		
	 *      *(-1,0) -2     	x(0, 0)      	*(1, 0) 2
	 *
	 *						*(-1, 0) -1
	 *
	 * Returns next point in the same orientation or -1 if it would go out of bounds. 
	 */					
	function getNextBasedOnOrientation(point, orientation) {
		var result = null;
		switch(orientation) {
			case 1:
				result = [point[0], point[1] + 1];
				break;
			case -1:
				result = [point[0], point[1] - 1];
				break;
			case 2:
				result = [point[0] + 1, point[1]];
				break;
			case -2:
				result = [point[0] - 1, point[1]];
				break;
		}
		return isOutOfBounds(result) ? -1 : result;
	}

	function isOutOfBounds(point) {
		return point[0] < 0 || point[0] >= GRID_WIDTH || point[1] < 0 || point[1] >= GRID_HEIGHT;
	}

	function isOnBorder(point) {
		return point[0] == 0 || point[0] == GRID_WIDTH || point[1] == 0 || point[1] == GRID_HEIGHT;
	}

	function isFree(point, visited) {
		return !visited[point[0]][point[1]];
	}

	function getPossibleNextMoves(point, visited) {
		var possible = [];
		var possiblePoint = null;
		var considered = [[point[0], point[1] + 1], [point[0] + 1, point[1]], 
			[point[0] - 1, point[1]], [point[0], point[1] - 1]];
		for (var i= 0; i < 4; i++) {
			possiblePoint = considered[i];
			if(!isOutOfBounds(possiblePoint) && isFree(possiblePoint, visited)) {
				possible.push(possiblePoint);
			}
		}
		return possible;
	}

	function initialiseVisited() {
		var visited = new Array(GRID_WIDTH);
		for (var i = 0; i < GRID_WIDTH; i++) {
			visited[i] = new Array(GRID_HEIGHT);
		}
		return visited;
	}
}

function defaultProgram(level) {
	  var program = new Program(
	          [TURN_LEFT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_LEFT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_LEFT,
	              FORWARD,
	              FORWARD,
	              FORWARD
	          ]);
	
	  level.play(program);
}

function trackDevelopment(level) {
	var program = new Program([]);
	
	$('#moveForward').click(function() {
		program.instructions.push(FORWARD);
    });
	
    $('#turnLeft').click(function() {
    	program.instructions.push(TURN_LEFT);
    });

    $('#turnRight').click(function() {
		program.instructions.push(TURN_RIGHT);
	});
    
    $('#play').click(function() {
    	level.play(program);
	});

	$('#randomRoad').click(function() {
		var ui = createUi();
		var points = generateRandomPathPoints([0,4], 0.5, 13);
		var nodes = generateNodes(points);  
		var van = new Van(nodes[0], nodes[1], ui);
		var map = new Map(nodes, ui);
	})
{'fraction_non_alphanumeric': 0.1555661274976213, 'fraction_numerical': 0.024072312083729782, 'mean_word_length': 2.592276144907724, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6245274', 'n_tokens_mistral': 4068, 'n_tokens_neox': 3516, 'n_words': 888}