public override void Update(IntVector3 position)
        {
            var neighborCells = new bool[4];
            var cellCounter = 0;

            foreach (IntVector2 offset in CellRange.Values2DCardinal()) {
                var absPos2D = offset + position.ToIntVector2();
                var absPos = new IntVector3(absPos2D.x, position.y, absPos2D.z);
                var cell = RegionManager.Instance.GetCellAt(absPos);

                neighborCells[cellCounter] = cell.wall != null;

                cellCounter++;
            }

            var rotation = (neighborCells[0] && neighborCells[2] ? Rotation.EAST : Rotation.NORTH);

            SpawnDoor(position, rotation);
        }
        private CellDefinition GetClosestWalkableCell(IntVector3 position)
        {
            var regionManager = RegionManager.Instance;
            var centerCell = regionManager.GetCellAt(position);

            /* If our target is a floor tile, return it */
            if (centerCell.floor != null) {
                return centerCell;
            }

            /* If not, search in a 9x9 grid around the target to find a walkable cell */
            foreach (var offset in CellRange.Values2D(false)) {
                var absPosGrid = offset + position.ToIntVector2();
                var cell = regionManager.GetCellAt(absPosGrid.ToIntVector3(position.y));

                if (cell != null && cell.floor != null) {
                    return cell;
                }
            }

            return null;
        }
        public override void Update(IntVector3 position)
        {
            var neighborCells = new short[9];
            var validMasks = new Dictionary<WallType, CellMask>(5);

            /* Properties used to refine valid tile masks */
            var containsEmptySpaces = false;
            var containsOtherWalls = false;
            var wallCount = 0;

            var cellCounter = -1;

            /* Grab surrounding block information */
            foreach (IntVector2 offset in CellRange.Values2D()) {
                var absPos2D = offset + position.ToIntVector2();
                var absPos = new IntVector3(absPos2D.x, position.y, absPos2D.z);
                CellDefinition cell;

                cellCounter++;

                cell = RegionManager.Instance.GetCellAt(absPos);
                containsEmptySpaces = containsEmptySpaces || CellDefinition.IsEmpty(cell);

                if (cell == null) {
                    neighborCells[cellCounter] = GameRegistry.EmptyObjectId;
                    continue;
                }

                if (cell.wall != null) {
                    if (!absPos.Equals(position)) {
                        containsOtherWalls = containsOtherWalls || cell.wall != null;
                    }

                    wallCount++;
                    neighborCells[cellCounter] = registry.GetObjectId<WallObject>();
                } else if (cell.floor != null) {
                    neighborCells[cellCounter] = registry.GetObjectId<FloorObject>();
                } else if (cell.containedObject.Is<DoorObject>()) {
                    neighborCells[cellCounter] = registry.GetObjectId<DoorObject>();
                } else {
                    neighborCells[cellCounter] = GameRegistry.EmptyObjectId;
                }
            }

            if (containsOtherWalls) {

                /* Default walls */
                AddValidMask(WallType.INNER_DEFAULT, validMasks);
                AddValidMask(WallType.INNER_END, validMasks);

                if (wallCount >= 3) {
                    AddValidMask(WallType.INNER_EDGE_INNER, validMasks);
                    AddValidMask(WallType.INNER_EDGE_T, validMasks);
                }

                if (wallCount >= 4) {
                    AddValidMask(WallType.INNER_EDGE_CROSS, validMasks);
                }

                if (containsEmptySpaces) {

                    AddValidMask(WallType.OUTER_DEFAULT, validMasks);

                    if (wallCount >= 3) {
                        AddValidMask(WallType.OUTER_EDGE_OUTER, validMasks);
                        AddValidMask(WallType.OUTER_EDGE_INNER, validMasks);
                        AddValidMask(WallType.OUTER_EDGE_T_INNER, validMasks);
                        AddValidMask(WallType.OUTER_EDGE_T_OUTER, validMasks);
                    }
                }
            }

            var calculatedType = WallType.OUTER_DEFAULT;
            var calculatedRotation = Rotation.NORTH;
            var foundMatch = false;

            foreach (var wallType in validMasks.Keys) {

                if (validMasks[wallType].Match(neighborCells, out calculatedRotation)) {
                    calculatedType = wallType;
                    foundMatch = true;
                    break;
                }
            }

            if (!foundMatch) {
                Logger.Warn("Could not find matching type for wall at {0}", position);
            }

            /* Spawn the new wall object and set transform */
            if (this.Type != calculatedType) {
                SpawnWall(calculatedType, position, calculatedRotation);
            } else if (this.rotation != calculatedRotation) {
                SetRotation(calculatedRotation);
            }
        }