UNPKG

maze-generation

Version:

A package to generate mazes using the depth first or hunt and kill algorithm. Mazes can be generated with seed values for reproducibility

313 lines (312 loc) 10.4 kB
import { Solver } from "../Solver"; import { Generator } from "../Generator"; import Prando from "prando"; const testOptions = { width: 4, height: 4, seed: "testseed", algorithm: "DEPTHFIRST", }; /* eslint-env jest */ describe("Constructor", () => { let gen; let testMaze; beforeEach(() => { gen = new Generator(testOptions.width, testOptions.height); testMaze = gen.generateMaze(testOptions.algorithm, new Prando(testOptions.seed)); }); it("Solves maze with a given seed", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: 3, column: 3, }; const testSolver = new Solver(testMaze.cells, testStart, testGoal); const expected = [ { column: 0, row: 0, }, { column: 0, row: 1, }, { column: 0, row: 2, }, { column: 1, row: 2, }, { column: 2, row: 2, }, { column: 3, row: 2, }, { column: 3, row: 3, }, ]; const actual = testSolver.path; expect(actual).toEqual(expected); }); describe("goal errors", () => { it("throws an error if the goal row is larger than the width of the maze", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: 4, column: 3, }; expect(() => { const testSolver = new Solver(testMaze.cells, testStart, testGoal); console.log(testSolver.path); }).toThrowError("start/goal rows must be less than maze height (3)."); }); it("throws an error if the goal column is larger than the width of the maze", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: 3, column: 4, }; expect(() => { const testSolver = new Solver(testMaze.cells, testStart, testGoal); console.log(testSolver.path); }).toThrowError("start/goal columns must be less than maze width (3)."); }); it("throws an error if the goal row is set to less than 0", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: -1, column: 3, }; expect(() => { const testSolver = new Solver(testMaze.cells, testStart, testGoal); console.log(testSolver.path); }).toThrowError("goal column/row must be greater than or equal to 0."); }); it("throws an error if the goal column is set to less than 0", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: 4, column: -1, }; expect(() => { const testSolver = new Solver(testMaze.cells, testStart, testGoal); console.log(testSolver.path); }).toThrowError("goal column/row must be greater than or equal to 0."); }); }); describe("start errors", () => { it("throws an error if the start row is larger than the width of the maze", () => { const testStart = { row: 4, column: 3, }; const testGoal = { row: 0, column: 0, }; expect(() => { const testSolver = new Solver(testMaze.cells, testStart, testGoal); console.log(testSolver.path); }).toThrowError("start/goal rows must be less than maze height (3)."); }); it("throws an error if the start column is larger than the width of the maze", () => { const testStart = { row: 3, column: 4, }; const testGoal = { row: 0, column: 0, }; expect(() => { const testSolver = new Solver(testMaze.cells, testStart, testGoal); console.log(testSolver.path); }).toThrowError("start/goal columns must be less than maze width (3)."); }); it("throws an error if the start row is less than 0", () => { const testStart = { row: -1, column: 4, }; const testGoal = { row: 0, column: 0, }; expect(() => { const testSolver = new Solver(testMaze.cells, testStart, testGoal); console.log(testSolver.path); }).toThrowError("start column/row must be greater than or equal to 0."); }); it("throws an error if the start column is less than 0", () => { const testStart = { row: 3, column: -1, }; const testGoal = { row: 0, column: 0, }; expect(() => { const testSolver = new Solver(testMaze.cells, testStart, testGoal); console.log(testSolver.path); }).toThrowError("start column/row must be greater than or equal to 0."); }); }); describe("no path found", () => { beforeEach(() => { // make goal cell impossible to get to testMaze.cells[2][3].walls = { left: true, right: true, up: true, down: true, }; testMaze.cells[3][2].walls = { left: true, right: true, up: true, down: true, }; testMaze.cells[3][3].walls = { left: true, right: true, up: true, down: true, }; }); it("returns empty array if no path can be found", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: 3, column: 3, }; const testSolver = new Solver(testMaze.cells, testStart, testGoal); const expected = []; const actual = testSolver.path; expect(actual).toEqual(expected); }); it("returns an empty string when showing no found path as string", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: 3, column: 3, }; const testSolver = new Solver(testMaze.cells, testStart, testGoal); const expected = ""; const actual = testSolver.toString(); expect(actual).toEqual(expected); }); it("returns an empty array when showing no found path as string", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: 3, column: 3, }; const testSolver = new Solver(testMaze.cells, testStart, testGoal); const expected = []; const actual = testSolver.toJSON(); expect(actual).toEqual(expected); }); }); }); describe("toString", () => { it("correctly creates string representation of the path", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: 3, column: 3, }; const gen = new Generator(testOptions.width, testOptions.height); const testMaze = gen.generateMaze(testOptions.algorithm, new Prando(testOptions.seed)); const testSolver = new Solver(testMaze.cells, testStart, testGoal); const actual = testSolver.toString(); const expected = " _ _ _ _\n" + "|S _ | |\n" + "|↓|_ _ _|\n" + "|↳ → → ↴|\n" + "|_|_ _ G|\n" + " ¯"; expect(actual).toEqual(expected); }); it("correctly creates string represenation if start and goal aren not in the corners", () => { const testStart = { row: 2, column: 0, }; const testGoal = { row: 1, column: 2, }; const gen = new Generator(testOptions.width, testOptions.height); const testMaze = gen.generateMaze(testOptions.algorithm, new Prando(testOptions.seed)); const testSolver = new Solver(testMaze.cells, testStart, testGoal); const actual = testSolver.toString(); const expected = " _ _ _ _\n" + "|↱ → ↴| |\n" + "|↑|_ G _|\n" + "|S _ _ |\n" + "|_|_ _ _|\n" + " "; expect(actual).toEqual(expected); }); }); describe("toJSON", () => { it("correctly creates JSON representation of the path", () => { const testStart = { row: 0, column: 0, }; const testGoal = { row: 3, column: 3, }; const gen = new Generator(testOptions.width, testOptions.height); const testMaze = gen.generateMaze(testOptions.algorithm, new Prando(testOptions.seed)); const testSolver = new Solver(testMaze.cells, testStart, testGoal); const actual = testSolver.toJSON(); const expected = [ { column: 0, row: 0 }, { column: 0, row: 1 }, { column: 0, row: 2 }, { column: 1, row: 2 }, { column: 2, row: 2 }, { column: 3, row: 2 }, { column: 3, row: 3 }, ]; expect(actual).toEqual(expected); }); });