Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import * as Events from 'events';
- import * as Util from 'util';
- class Field extends Events.EventEmitter{
- constructor(width, height) {
- super();
- this.field = Array(width * height);
- this.width = width;
- this.height = height;
- this.start = {
- x : 1,
- y : 1
- };
- this.target = {
- x : 2,
- y : 2
- };
- this.dirty = true;
- this.colors = new Set();
- this.colors.add("#ffffff");
- this.initialize();
- }
- get(arg1, arg2) {
- if(arg2 === undefined) {
- return this.get(arg1.x, arg1.y);
- }
- else {
- return this.field[arg1 + arg2 * this.width];
- }
- }
- *[Symbol.iterator]() {
- for(var x = 0; x < this.width; x++) {
- for(var y = 0; y < this.height; y++) {
- yield {x, y, tile : this.field[x + y * this.width]};
- }
- }
- }
- coordInBounds(coord) {
- return coord.x > 0 && coord.y > 0 && coord.x < this.width - 1 && coord.y < this.height -1;
- }
- coordValid(coord) {
- return this.coordInBounds(coord) && !(coord.x == this.start.x && coord.y == this.start.y) && !(coord.x == this.target.x && coord.y == this.target.y);
- }
- placeWallAt(coord) {
- if(this.coordValid(coord)) {
- let tile = this.get(coord);
- if(!tile.wall) {
- let old = tile.wall;
- tile.wall = true;
- if(!this.recreatePath()) {
- tile.wall = old;
- }
- else {
- this.markDirty();
- this.emit("wall-placed", coord, tile);
- }
- }
- }
- }
- removeWallAt(coord) {
- if(this.coordValid(coord)) {
- let tile = this.get(coord);
- if(tile.wall) {
- let old = tile.wall;
- tile.wall = false;
- if(!this.recreatePath()) {
- tile.wall = old;
- }
- else {
- this.markDirty();
- this.emit("wall-removed", coord, tile);
- }
- }
- }
- }
- placeStart(coord) {
- if(this.coordValid(coord) && !(coord.x == this.start.x && coord.y == this.start.y)) {
- let old = this.start;
- this.markDirty();
- this.start = coord;
- this.get(coord).wall = false;
- if(!this.recreatePath()) {
- this.placeStart(old);
- }
- else {
- this.emit("start", coord, old);
- }
- }
- }
- placeTarget(coord) {
- if(this.coordValid(coord) && !(coord.x == this.target.x && coord.y == this.target.y)) {
- let old = this.target;
- this.markDirty();
- this.target = coord;
- this.get(coord).wall = false;
- if(!this.recreatePath()) {
- this.placeTarget(old);
- }
- else {
- this.emit("target", coord, old);
- }
- }
- }
- coordInBound(arg1, arg2) {
- if(arg2 === undefined) {
- return this.coordInBound(arg1.x, arg1.y);
- }
- else {
- return arg1 >= 0 && arg1 < this.width && arg2 >= 0 && arg2 < this.height;
- }
- }
- colorize(coord, color) {
- if(this.coordInBound(coord)) {
- this.markDirty();
- let tile = this.get(coord);
- let old = tile.color;
- let changed = false;
- tile.color = color;
- this.emit("colored", color, tile);
- if(!this.colors.has(color)) {
- this.colors.add(color);
- changed = true;
- }
- if(!this.field.find((t) => t.color == old)) {
- this.colors.delete(old);
- changed = true;
- }
- if(changed) {
- this.emit("colors", [...this.colors]);
- }
- }
- }
- recreatePath() {
- let createNode = (x, y) => {
- return {
- x : x,
- y : y,
- f : 0,
- g : 0,
- h : 0
- };
- };
- let findNeighbors = (n) => {
- let l = [];
- let s = this.getSurroundings(n.x, n.y);
- if(!s.left) { l.push(createNode(n.x - 1, n.y)); }
- if(!s.top) { l.push(createNode(n.x, n.y - 1)); }
- if(!s.right) { l.push(createNode(n.x + 1, n.y));}
- if(!s.bottom) { l.push(createNode(n.x, n.y + 1)); }
- return l;
- };
- let open = [];
- let closed = [];
- let solution;
- open.push(createNode(this.start.x, this.start.y));
- while(open.length) {
- let low = 0;
- open.forEach((n, i) => {
- if(n.f < open[low].f) { low = i; }
- });
- let node = open[low];
- if(node.x == this.target.x && node.y == this.target.y) {
- let c = node;
- let path = [];
- while(c.parent) {
- path.push(c);
- c = c.parent;
- }
- path.push(this.start);
- solution = path;
- }
- open.splice(open.indexOf(node), 1);
- closed.push(node);
- let neighbors = findNeighbors(node);
- neighbors.forEach((n, i) => {
- if(!closed.find((t) => n.x == t.x && n.y == t.y)) {
- let g = node.g + 1;
- let isBest = false;
- if(!open.find((t) => n.x == t.x && n.y == t.y)) {
- isBest = true;
- n.h = Math.sqrt(Math.pow(this.target.x - n.x, 2) + Math.pow(this.target.y - n.y, 2));
- open.push(n);
- }
- else if(g < n.g) {
- isBest = true;
- }
- if(isBest) {
- n.parent = node;
- n.g = g;
- n.f = n.g + n.h;
- }
- }
- });
- }
- if(solution) {
- for(let i = 0; i < this.width * this.height; i++) {
- this.field[i].path = false;
- }
- solution.forEach((coord) => {
- this.get(coord).path = true;
- });
- return true;
- }
- else {
- return false;
- }
- }
- markDirty() {
- this.dirty = true;
- }
- markSober() {
- this.dirty = false;
- }
- getSurroundings(arg1, arg2) {
- if(arg2 === undefined) {
- return this.getSurroundings(arg1.x, arg1.y);
- }
- else {
- return {
- left : this.wallAt(arg1 - 1, arg2),
- right : this.wallAt(arg1 + 1, arg2),
- top : this.wallAt(arg1, arg2 - 1),
- bottom : this.wallAt(arg1, arg2 + 1)
- };
- }
- }
- getPathSurroundings(arg1, arg2) {
- if(arg2 === undefined) {
- return this.getPathSurroundings(arg1.x, arg1.y);
- }
- else {
- return {
- left : this.pathAt(arg1 - 1, arg2),
- right : this.pathAt(arg1 + 1, arg2),
- top : this.pathAt(arg1, arg2 - 1),
- bottom : this.pathAt(arg1, arg2 + 1)
- };
- }
- }
- wallAt(arg1, arg2) {
- if(arg2 === undefined) {
- return wallAt(arg1.x, arg1.y);
- }
- else {
- return arg1 >= 0 &&
- arg1 < this.width &&
- arg2 >= 0 &&
- arg2 < this.height &&
- this.get(arg1, arg2).wall;
- }
- }
- pathAt(arg1, arg2) {
- if(arg2 === undefined) {
- return pathAt(arg1.x, arg1.y);
- }
- else {
- return arg1 >= 0 &&
- arg1 < this.width &&
- arg2 >= 0 &&
- arg2 < this.height &&
- this.get(arg1, arg2).path;
- }
- }
- initialize() {
- for(let i = 0; i < this.width * this.height; i++) {
- let isWall = i < this.width ||
- i >= this.width * (this.height - 1) ||
- i % this.width == 0 ||
- i % this.width == this.width - 1;
- this.field[i] = {
- wall : isWall,
- path: false,
- color : "#ffffff"
- };
- }
- this.recreatePath();
- }
- };
- export default Field;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement