map connectedness checker (floodfill)
This commit is contained in:
		| @@ -111,6 +111,15 @@ export class Point { | ||||
|     let dy = other.y - this.y; | ||||
|     return Math.sqrt(dx * dx + dy * dy); | ||||
|   } | ||||
|  | ||||
|   neighbors() : Point[] { | ||||
|     return [ | ||||
|       new Point(this.x, this.y-1), | ||||
|       new Point(this.x-1, this.y), | ||||
|       new Point(this.x, this.y+1), | ||||
|       new Point(this.x+1, this.y), | ||||
|     ]; | ||||
|   } | ||||
| } | ||||
|  | ||||
| export class Size { | ||||
| @@ -264,19 +273,27 @@ export class Grid<T> { | ||||
|     return new Grid(this.size, (xy) => cbCell(this.get(xy), xy)); | ||||
|   } | ||||
|  | ||||
|   #checkPosition(position: Point) { | ||||
|     if ( | ||||
|       position.x < 0 || | ||||
|   #invalidPosition(position: Point) : boolean { | ||||
|     return position.x < 0 || | ||||
|       position.x >= this.size.w || | ||||
|       Math.floor(position.x) != position.x || | ||||
|       position.y < 0 || | ||||
|       position.y >= this.size.h || | ||||
|       Math.floor(position.y) != position.y | ||||
|     ) { | ||||
|       Math.floor(position.y) != position.y;; | ||||
|   } | ||||
|   #checkPosition(position: Point) { | ||||
|     if (this.#invalidPosition(position)) { | ||||
|       throw new Error(`invalid position for ${this.size}: ${position}`); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   maybeGet(position: Point): T | null { | ||||
|     if (this.#invalidPosition(position)) { | ||||
|       return null; | ||||
|     } | ||||
|     return this.#data[position.y][position.x]; | ||||
|   } | ||||
|  | ||||
|   get(position: Point): T { | ||||
|     this.#checkPosition(position); | ||||
|     return this.#data[position.y][position.x]; | ||||
|   | ||||
| @@ -105,6 +105,51 @@ export class LoadedNewMap { | ||||
|   getZoneLabel(point: Point): string | null { | ||||
|     return this.#zoneLabels.get(point); | ||||
|   } | ||||
|  | ||||
|   isConnected(): boolean { | ||||
|     const size = this.#size; | ||||
|     let reached = new Grid<boolean>(size, ()=>false); | ||||
|  | ||||
|     // find starting location | ||||
|     const found: Point | null = (()=>{ | ||||
|       for(let x = 0; x < size.w; x++) { | ||||
|         for(let y = 0; y < size.w; y++) { | ||||
|           const p = new Point(x, y) | ||||
|           if (this.#architecture.get(p) == Architecture.Floor) { | ||||
|             return p; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       return null; | ||||
|     })(); | ||||
|     if (found === null) { | ||||
|       // technically, all open floors on the map are indeed connected | ||||
|       return true | ||||
|     } | ||||
|  | ||||
|     let stack : Point[] = [found]; | ||||
|     reached.set(found, true); | ||||
|     while (stack.length > 0) { | ||||
|       const loc = stack.pop() as Point; | ||||
|       for (var p of loc.neighbors()) { | ||||
|         if ((this.#architecture.maybeGet(p) === Architecture.Floor) && !reached.get(p)) { | ||||
|           reached.set(p, true); | ||||
|           stack.push(p); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     for(let x = 0; x < size.w; x++) { | ||||
|       for(let y = 0; y < size.w; y++) { | ||||
|         const p = new Point(x, y) | ||||
|         if (this.#architecture.get(p) == Architecture.Floor && !reached.get(p)) { | ||||
|           return false; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| export class CellView { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user