Advertisement
Guest User

Untitled

a guest
Nov 30th, 2015
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import * as Events from 'events';
  2. import * as Util from 'util';
  3.  
  4. class Field extends Events.EventEmitter{
  5.     constructor(width, height) {
  6.         super();
  7.         this.field = Array(width * height);
  8.         this.width = width;
  9.         this.height = height;
  10.         this.start = {
  11.             x : 1,
  12.             y : 1
  13.         };
  14.         this.target = {
  15.             x : 2,
  16.             y : 2
  17.         };
  18.         this.dirty = true;
  19.         this.colors = new Set();
  20.         this.colors.add("#ffffff");
  21.         this.initialize();
  22.     }
  23.  
  24.     get(arg1, arg2) {
  25.         if(arg2 === undefined) {
  26.             return this.get(arg1.x, arg1.y);
  27.         }
  28.         else {
  29.             return this.field[arg1 + arg2 * this.width];
  30.         }
  31.     }
  32.  
  33.     *[Symbol.iterator]() {
  34.         for(var x = 0; x < this.width; x++) {
  35.             for(var y = 0; y < this.height; y++) {
  36.                 yield {x, y, tile : this.field[x + y * this.width]};
  37.             }
  38.         }
  39.     }
  40.  
  41.     coordInBounds(coord) {
  42.         return coord.x > 0 && coord.y > 0 && coord.x < this.width - 1 && coord.y < this.height -1;
  43.     }
  44.  
  45.     coordValid(coord) {
  46.         return this.coordInBounds(coord) && !(coord.x == this.start.x && coord.y == this.start.y) && !(coord.x == this.target.x && coord.y == this.target.y);
  47.     }
  48.  
  49.     placeWallAt(coord) {
  50.         if(this.coordValid(coord)) {
  51.             let tile = this.get(coord);
  52.             if(!tile.wall) {
  53.                 let old = tile.wall;
  54.                 tile.wall = true;
  55.                 if(!this.recreatePath()) {
  56.                     tile.wall = old;
  57.                 }
  58.                 else {
  59.                     this.markDirty();
  60.                     this.emit("wall-placed", coord, tile);
  61.                 }
  62.             }
  63.         }
  64.     }
  65.  
  66.     removeWallAt(coord) {
  67.         if(this.coordValid(coord)) {
  68.             let tile = this.get(coord);
  69.             if(tile.wall) {
  70.                 let old = tile.wall;
  71.                 tile.wall = false;
  72.                 if(!this.recreatePath()) {
  73.                     tile.wall = old;
  74.                 }
  75.                 else {
  76.                     this.markDirty();
  77.                     this.emit("wall-removed", coord, tile);
  78.                 }
  79.             }
  80.         }
  81.     }
  82.  
  83.     placeStart(coord) {
  84.         if(this.coordValid(coord) && !(coord.x == this.start.x && coord.y == this.start.y)) {
  85.             let old = this.start;
  86.             this.markDirty();
  87.             this.start = coord;
  88.             this.get(coord).wall = false;
  89.             if(!this.recreatePath()) {
  90.                 this.placeStart(old);
  91.             }
  92.             else {
  93.                 this.emit("start", coord, old);
  94.             }
  95.         }
  96.     }
  97.  
  98.     placeTarget(coord) {
  99.         if(this.coordValid(coord) && !(coord.x == this.target.x && coord.y == this.target.y)) {
  100.             let old = this.target;
  101.             this.markDirty();
  102.             this.target = coord;
  103.             this.get(coord).wall = false;
  104.             if(!this.recreatePath()) {
  105.                 this.placeTarget(old);
  106.             }
  107.             else {
  108.                 this.emit("target", coord, old);
  109.             }
  110.         }
  111.     }
  112.  
  113.     coordInBound(arg1, arg2) {
  114.         if(arg2 === undefined) {
  115.             return this.coordInBound(arg1.x, arg1.y);
  116.         }
  117.         else {
  118.             return arg1 >= 0 && arg1 < this.width && arg2 >= 0 && arg2 < this.height;
  119.         }
  120.     }
  121.  
  122.     colorize(coord, color) {
  123.         if(this.coordInBound(coord)) {
  124.             this.markDirty();
  125.             let tile = this.get(coord);
  126.             let old = tile.color;
  127.             let changed = false;
  128.             tile.color = color;
  129.             this.emit("colored", color, tile);
  130.             if(!this.colors.has(color)) {
  131.                 this.colors.add(color);
  132.                 changed = true;
  133.             }
  134.             if(!this.field.find((t) => t.color == old)) {
  135.                 this.colors.delete(old);
  136.                 changed = true;
  137.             }
  138.             if(changed) {
  139.                 this.emit("colors", [...this.colors]);
  140.             }
  141.         }
  142.     }
  143.  
  144.     recreatePath() {
  145.  
  146.         let createNode = (x, y) => {
  147.             return {
  148.                 x : x,
  149.                 y : y,
  150.                 f : 0,
  151.                 g : 0,
  152.                 h : 0
  153.             };
  154.         };
  155.  
  156.         let findNeighbors = (n)  => {
  157.             let l = [];
  158.             let s = this.getSurroundings(n.x, n.y);
  159.             if(!s.left) { l.push(createNode(n.x - 1, n.y)); }
  160.             if(!s.top) { l.push(createNode(n.x, n.y - 1)); }
  161.             if(!s.right) { l.push(createNode(n.x + 1, n.y));}
  162.             if(!s.bottom) { l.push(createNode(n.x, n.y + 1)); }
  163.             return l;
  164.         };
  165.         let open = [];
  166.         let closed = [];
  167.         let solution;
  168.         open.push(createNode(this.start.x, this.start.y));
  169.  
  170.         while(open.length) {
  171.             let low = 0;
  172.             open.forEach((n, i) => {
  173.                 if(n.f < open[low].f) { low = i; }
  174.             });
  175.             let node = open[low];
  176.             if(node.x == this.target.x && node.y == this.target.y) {
  177.                 let c = node;
  178.                 let path = [];
  179.                 while(c.parent) {
  180.                     path.push(c);
  181.                     c = c.parent;
  182.                 }
  183.                 path.push(this.start);
  184.                 solution = path;
  185.             }
  186.             open.splice(open.indexOf(node), 1);
  187.             closed.push(node);
  188.             let neighbors = findNeighbors(node);
  189.             neighbors.forEach((n, i) => {
  190.                 if(!closed.find((t) => n.x == t.x && n.y == t.y)) {
  191.                     let g = node.g + 1;
  192.                     let isBest = false;
  193.                     if(!open.find((t) => n.x == t.x && n.y == t.y)) {
  194.                         isBest = true;
  195.                         n.h = Math.sqrt(Math.pow(this.target.x - n.x, 2) + Math.pow(this.target.y - n.y, 2));
  196.                         open.push(n);
  197.                     }
  198.                     else if(g < n.g) {
  199.                         isBest = true;
  200.                     }
  201.                     if(isBest) {
  202.                         n.parent = node;
  203.                         n.g = g;
  204.                         n.f = n.g + n.h;
  205.                     }
  206.                 }
  207.             });
  208.         }
  209.         if(solution) {
  210.             for(let i = 0; i < this.width * this.height; i++) {
  211.                 this.field[i].path = false;
  212.             }
  213.             solution.forEach((coord) => {
  214.                 this.get(coord).path = true;
  215.             });
  216.             return true;
  217.         }
  218.         else {
  219.             return false;
  220.         }
  221.     }
  222.  
  223.     markDirty() {
  224.         this.dirty = true;
  225.     }
  226.  
  227.     markSober() {
  228.         this.dirty = false;
  229.     }
  230.  
  231.     getSurroundings(arg1, arg2) {
  232.         if(arg2 === undefined) {
  233.             return this.getSurroundings(arg1.x, arg1.y);
  234.         }
  235.         else {
  236.             return  {
  237.                 left : this.wallAt(arg1 - 1, arg2),
  238.                 right : this.wallAt(arg1 + 1, arg2),
  239.                 top : this.wallAt(arg1, arg2 - 1),
  240.                 bottom : this.wallAt(arg1, arg2 + 1)
  241.             };
  242.         }
  243.     }
  244.  
  245.     getPathSurroundings(arg1, arg2) {
  246.         if(arg2 === undefined) {
  247.             return this.getPathSurroundings(arg1.x, arg1.y);
  248.         }
  249.         else {
  250.             return  {
  251.                 left : this.pathAt(arg1 - 1, arg2),
  252.                 right : this.pathAt(arg1 + 1, arg2),
  253.                 top : this.pathAt(arg1, arg2 - 1),
  254.                 bottom : this.pathAt(arg1, arg2 + 1)
  255.             };
  256.         }
  257.     }
  258.  
  259.     wallAt(arg1, arg2) {
  260.         if(arg2 === undefined) {
  261.             return wallAt(arg1.x, arg1.y);
  262.         }
  263.         else {
  264.             return arg1 >= 0 &&
  265.                 arg1 < this.width &&
  266.                 arg2 >= 0 &&
  267.                 arg2 < this.height &&
  268.                 this.get(arg1, arg2).wall;
  269.         }
  270.     }
  271.  
  272.     pathAt(arg1, arg2) {
  273.         if(arg2 === undefined) {
  274.             return pathAt(arg1.x, arg1.y);
  275.         }
  276.         else {
  277.             return arg1 >= 0 &&
  278.                 arg1 < this.width &&
  279.                 arg2 >= 0 &&
  280.                 arg2 < this.height &&
  281.                 this.get(arg1, arg2).path;
  282.         }
  283.     }
  284.  
  285.     initialize() {
  286.         for(let i = 0; i < this.width * this.height; i++) {
  287.             let isWall = i < this.width ||
  288.                 i >= this.width * (this.height - 1) ||
  289.                 i % this.width == 0 ||
  290.                 i % this.width == this.width - 1;
  291.             this.field[i] = {
  292.                 wall : isWall,
  293.                 path: false,
  294.                 color : "#ffffff"
  295.             };
  296.         }
  297.         this.recreatePath();
  298.     }
  299. };
  300.  
  301. export default Field;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement