<commit_before>/// <reference path="../libs/phaser/typescript/phaser.d.ts"/>

/// <reference path="coordinates.ts"/>
/// <reference path="gnome.ts"/>
/// <reference path="world_constants.ts"/>

/**
 * This class is responsible for keeping track of the world state and handling collisions.
 */
class GameWorld {
	constructor(public game: Phaser.Game) {}

	public level: Level;
	public gnome: Gnome;

	/**
	 * Loads the level with the provided name. It should be a JSON file that is loaded into the cache
	 * in the preloader.
	 */
	loadLevel(levelName: string) {
		let levelDefinition = this.game.cache.getJSON(levelName).LEVEL_DEFINITION;
		this.level = new Level(levelDefinition);
		this.level.renderStage(this.game);
		this.gnome = new Gnome(this.game, 2, 2);
	}

	/**
	 * Rotate active gnome left
	 */
	rotateLeft() {
		this.gnome.rotateLeft();
	}

	/**
	 * Rotate active gnome right
	 */
	rotateRight() {
		this.gnome.rotateRight();
	}

	tryMove() {
		let newLocation = this.gnome.location.getNeighbor(this.gnome.direction);
		if (this.level.pointIsPassable(newLocation)) {
			this.gnome.location = newLocation;
		}

		let causeOfDeath = this.level.getPointCauseOfDeath(newLocation);
		if (causeOfDeath !== null) {
			this.gnome.die(causeOfDeath);
			this.gnome = new Gnome(this.game, 2, 2);
		}
	}
}

class Level {
	private layout: Array<Array<WorldConstants.BlockType>>;

	constructor(levelDefinition) {
		this.layout = levelDefinition.layout;
	}

	pointIsPassable(point: Point): boolean {
		if (this.layout[point.x] === undefined || this.layout[point.x][point.y] === undefined) {
			return true;
		}
		//TODO some entities are impassable
		return true;
	}

	getPointCauseOfDeath(point: Point): CauseOfDeath {
		if (this.layout[point.x] === undefined || this.layout[point.x][point.y] === undefined) {
			return CauseOfDeath.FALLING;
		}

		if (this.layout[point.x][point.y] === WorldConstants.BlockType.WATER) {
			return CauseOfDeath.DROWNING;
		}

		return null;
	}

	renderStage(game: Phaser.Game) {
		let rows = this.layout.length;
		let columns = this.layout[0].length;

		for (let row = 0; row < rows; row++) {
			for (let column = 0; column < columns; column++) {
				this.renderBlock(game, row, column, this.layout[row][column]);
			}
		}<commit_msg>Flip x & y coordinates for layout array access<commit_after>/// <reference path="../libs/phaser/typescript/phaser.d.ts"/>

/// <reference path="coordinates.ts"/>
/// <reference path="gnome.ts"/>
/// <reference path="world_constants.ts"/>

/**
 * This class is responsible for keeping track of the world state and handling collisions.
 */
class GameWorld {
	constructor(public game: Phaser.Game) {}

	public level: Level;
	public gnome: Gnome;

	/**
	 * Loads the level with the provided name. It should be a JSON file that is loaded into the cache
	 * in the preloader.
	 */
	loadLevel(levelName: string) {
		let levelDefinition = this.game.cache.getJSON(levelName).LEVEL_DEFINITION;
		this.level = new Level(levelDefinition);
		this.level.renderStage(this.game);
		this.gnome = new Gnome(this.game, 2, 2);
	}

	/**
	 * Rotate active gnome left
	 */
	rotateLeft() {
		this.gnome.rotateLeft();
	}

	/**
	 * Rotate active gnome right
	 */
	rotateRight() {
		this.gnome.rotateRight();
	}

	tryMove() {
		let newLocation = this.gnome.location.getNeighbor(this.gnome.direction);
		if (this.level.pointIsPassable(newLocation)) {
			this.gnome.location = newLocation;
		}

		let causeOfDeath = this.level.getPointCauseOfDeath(newLocation);
		if (causeOfDeath !== null) {
			this.gnome.die(causeOfDeath);
			this.gnome = new Gnome(this.game, 2, 2);
		}
	}
}

class Level {
	//Array access should be done in [y][x] order!
	private layout: Array<Array<WorldConstants.BlockType>>;

	constructor(levelDefinition) {
		this.layout = levelDefinition.layout;
	}

	pointIsPassable(point: Point): boolean {
		//TODO some entities are impassable
		return true;
	}

	getPointCauseOfDeath(point: Point): CauseOfDeath {
		let block = this.getBlock(point);
		if (block === null) {
			return CauseOfDeath.FALLING;
		}

		if (block === WorldConstants.BlockType.WATER) {
			return CauseOfDeath.DROWNING;
		}

		return null;
	}

	private getBlock(point: Point) {
		if (this.layout[point.y] === undefined || this.layout[point.y][point.x] === undefined) {
			return null;
		}

		return this.layout[point.y][point.x];
	}

	renderStage(game: Phaser.Game) {
		let rows = this.layout.length;
		let columns = this.layout[0].length;

		for (let row = 0; row < rows; row++) {
			for (let column = 0; column < columns; column++) {
				this.renderBlock(game, column, row, this.layout[row][column]);
			}
		}
{'fraction_non_alphanumeric': 0.14612562054824088, 'fraction_numerical': 0.00302180012950572, 'mean_word_length': 3.762589928057554, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4299564', 'n_tokens_mistral': 1736, 'n_tokens_neox': 1514, 'n_words': 361}