diff --git a/src/MazeMap.spec.ts b/src/MazeMap.spec.ts index f54557a..36a7de4 100644 --- a/src/MazeMap.spec.ts +++ b/src/MazeMap.spec.ts @@ -104,6 +104,16 @@ }); }); + describe("When two tiles have the same id", function(){ + const maze = createMinimalisticMaze(); + maze.layout[0][1].id = maze.layout[0][0].id; + const result = maze.validate(); + it("then it is invalid", function(){ + expect(result.length).to.be.greaterThan(0); + expect(result).to.contain(MazeValidationError.TileIdsNotUnique); + }); + }); + describe("When it is not rectangular shaped", function(){ const maze = createMinimalisticMaze(); const tile = new MazeTile("3"); @@ -187,4 +197,36 @@ expect(result).to.contain(MazeValidationError.PathWithoutDestination); }); }); + + describe("When the maze is empty", function(){ + const maze = new MazeMap("id"); + const result = maze.validate(); + it("then it is invalid", function(){ + expect(result.length).to.be.greaterThan(0); + expect(result).to.contain(MazeValidationError.WrongShape); + }); + }); + + describe("When the start position is outside the map", function(){ + const maze = createMinimalisticMaze(); + maze.startPosition[0] = -1; + const result = maze.validate(); + it("then it is invalid", function(){ + expect(result.length).to.be.greaterThan(0); + expect(result).to.contain(MazeValidationError.StartPositionNotOnMap); + }); + }); + + describe("When the start position has no pathways", function(){ + const maze = createMinimalisticMaze(); + const tile = new MazeTile("3"); + tile.paths.push(Direction.none); + maze.layout[0].push(tile); + maze.startPosition[1] = 2; + const result = maze.validate(); + it("then it is invalid", function(){ + expect(result.length).to.be.greaterThan(0); + expect(result).to.contain(MazeValidationError.InvalidStartPosition); + }); + }); }); diff --git a/src/MazeMap.spec.ts b/src/MazeMap.spec.ts index f54557a..36a7de4 100644 --- a/src/MazeMap.spec.ts +++ b/src/MazeMap.spec.ts @@ -104,6 +104,16 @@ }); }); + describe("When two tiles have the same id", function(){ + const maze = createMinimalisticMaze(); + maze.layout[0][1].id = maze.layout[0][0].id; + const result = maze.validate(); + it("then it is invalid", function(){ + expect(result.length).to.be.greaterThan(0); + expect(result).to.contain(MazeValidationError.TileIdsNotUnique); + }); + }); + describe("When it is not rectangular shaped", function(){ const maze = createMinimalisticMaze(); const tile = new MazeTile("3"); @@ -187,4 +197,36 @@ expect(result).to.contain(MazeValidationError.PathWithoutDestination); }); }); + + describe("When the maze is empty", function(){ + const maze = new MazeMap("id"); + const result = maze.validate(); + it("then it is invalid", function(){ + expect(result.length).to.be.greaterThan(0); + expect(result).to.contain(MazeValidationError.WrongShape); + }); + }); + + describe("When the start position is outside the map", function(){ + const maze = createMinimalisticMaze(); + maze.startPosition[0] = -1; + const result = maze.validate(); + it("then it is invalid", function(){ + expect(result.length).to.be.greaterThan(0); + expect(result).to.contain(MazeValidationError.StartPositionNotOnMap); + }); + }); + + describe("When the start position has no pathways", function(){ + const maze = createMinimalisticMaze(); + const tile = new MazeTile("3"); + tile.paths.push(Direction.none); + maze.layout[0].push(tile); + maze.startPosition[1] = 2; + const result = maze.validate(); + it("then it is invalid", function(){ + expect(result.length).to.be.greaterThan(0); + expect(result).to.contain(MazeValidationError.InvalidStartPosition); + }); + }); }); diff --git a/src/MazeMap.ts b/src/MazeMap.ts index c9a497f..5265cdf 100644 --- a/src/MazeMap.ts +++ b/src/MazeMap.ts @@ -93,17 +93,22 @@ PathWithoutDestination = "Pathways must have a corresponding destination tile.", WrongShape = "Maze must be shaped like a rectangle.", NoHolesAllowed = "Maze has null-tiles.", + TileIdsNotUnique = "Some tiles have the same id.", + StartPositionNotOnMap = "The starting tile has to be on the map.", + InvalidStartPosition = "The starting tile needs to have pathways.", } export class MazeMap { public id:string; public layout:MazeTile[][]; + public startPosition: number[]; constructor(id:string) { this.id = id; this.layout = []; + this.startPosition = [0, 0]; } public getRepresentation(): number[][] @@ -119,9 +124,9 @@ return output; } - public validate(): string[] + public validate(): MazeValidationError[] { - const errors:string[] = []; + const errors:MazeValidationError[] = []; if(this.id == null || this.id === "") { errors.push(MazeValidationError.InvalidID); @@ -129,6 +134,7 @@ let hasInvalidTiles = false; let hasNullTiles = false; + let hasIDDuplicates = false; for (const row of this.layout) { if(row == null) { @@ -145,6 +151,24 @@ { hasInvalidTiles = true; } + + if(!hasIDDuplicates){ + for (const row2 of this.layout) { + if(row2 == null){ + continue; + } + for (const tile2 of row2) { + if(tile2 == null || tile2 === tile) + { + continue; + } + if(tile2.id === tile.id) + { + hasIDDuplicates = true; + } + } + } + } } } if(hasInvalidTiles) @@ -155,14 +179,26 @@ { errors.push(MazeValidationError.NoHolesAllowed); } + if(hasIDDuplicates) + { + errors.push(MazeValidationError.TileIdsNotUnique); + } let hasWrongShape = false; - for (const row of this.layout) { - if(row == null || row.length !== this.layout[0].length) - { - errors.push(MazeValidationError.WrongShape); - hasWrongShape = true; - break; + if(this.layout.length === 0) + { + errors.push(MazeValidationError.WrongShape); + hasWrongShape = true; + } + else + { + for (const row of this.layout) { + if(row == null || row.length !== this.layout[0].length) + { + errors.push(MazeValidationError.WrongShape); + hasWrongShape = true; + break; + } } } @@ -204,6 +240,34 @@ } } + if(this.layout != null){ + if(this.startPosition[0] < 0 || this.startPosition[0] >= this.layout.length) + { + errors.push(MazeValidationError.StartPositionNotOnMap); + } + else if(this.layout.length>0 + && (this.startPosition[1] < 0 || this.startPosition[1] >= this.layout[0].length)) + { + errors.push(MazeValidationError.StartPositionNotOnMap); + } + else if(this.layout.length > 0 + && this.layout[this.startPosition[0]][this.startPosition[1]] != null) + { + const start = this.layout[this.startPosition[0]][this.startPosition[1]]; + let hasPaths = false; + for (const dir of start.paths) { + if(dir !== Direction.none){ + hasPaths = true; + break; + } + } + if(!hasPaths) + { + errors.push(MazeValidationError.InvalidStartPosition); + } + } + } + return errors; } }