Beispiel #1
0
        public static PatternReplaceCount FloorPatternRect(VMArchitecture target, Rectangle rect, ushort dir, ushort pattern, sbyte level) //returns floors covered
        {
            PatternReplaceCount floorsCovered = new PatternReplaceCount(true);

            if (rect.Width == 0 && rect.Height == 0)
            {
                //dot mode, just fill a tile. can be a diagonal.
                if (rect.X < 0 || rect.X >= target.Width || rect.Y < 0 || rect.Y >= target.Width)
                {
                    return(floorsCovered);
                }
                var wall = target.GetWall((short)rect.X, (short)rect.Y, level);
                if ((wall.Segments & AnyDiag) > 0 && pattern < 65534)
                {
                    bool side = ((wall.Segments & WallSegments.HorizontalDiag) > 0) ? (dir < 2) : (dir < 1 || dir > 2);
                    if (side)
                    {
                        if (wall.TopLeftStyle != pattern)
                        {
                            floorsCovered.Add(wall.TopLeftStyle);
                            wall.TopLeftStyle = pattern;
                        }
                    }
                    else
                    {
                        if (wall.TopLeftPattern != pattern)
                        {
                            floorsCovered.Add(wall.TopLeftPattern);
                            wall.TopLeftPattern = pattern;
                        }
                    }
                    target.SetWall((short)rect.X, (short)rect.Y, level, wall);
                }
                else if ((wall.Segments & AnyDiag) == 0)
                {
                    var floor = target.GetFloor((short)rect.X, (short)rect.Y, level);
                    if (floor.Pattern != pattern)
                    {
                        var old = floor.Pattern;
                        floor.Pattern = pattern;
                        if (target.SetFloor((short)rect.X, (short)rect.Y, level, floor, false))
                        {
                            floorsCovered.DAdd(old);
                        }
                    }
                }
                return(floorsCovered);
            }

            var xEnd = Math.Min(target.Width, rect.X + rect.Width + 1);
            var yEnd = Math.Min(target.Height, rect.Y + rect.Height + 1);

            for (int y = Math.Max(0, rect.Y); y < yEnd; y++)
            {
                for (int x = Math.Max(0, rect.X); x < xEnd; x++)
                {
                    var wall = target.GetWall((short)x, (short)y, level);
                    if ((wall.Segments & AnyDiag) > 0) //diagonal floors are stored in walls
                    {
                        if (pattern < 65534)
                        {
                            continue;
                        }
                        if (wall.TopLeftStyle != pattern)
                        {
                            wall.TopLeftStyle = pattern;
                            floorsCovered.Add(wall.TopLeftStyle);
                        }

                        if (wall.TopLeftPattern != pattern)
                        {
                            wall.TopLeftPattern = pattern;
                            floorsCovered.Add(wall.TopLeftPattern);
                        }
                        target.SetWall((short)x, (short)y, level, wall);
                    }
                    else
                    {
                        var floor = target.GetFloor((short)x, (short)y, level);
                        if (floor.Pattern != pattern)
                        {
                            var old = floor.Pattern;
                            floor.Pattern = pattern;
                            if (target.SetFloor((short)x, (short)y, level, floor, false))
                            {
                                floorsCovered.DAdd(old);
                            }
                        }
                    }
                }
            }
            return(floorsCovered);
        }
Beispiel #2
0
        private static PatternReplaceCount SpreadOnto(WallTile[] walls, int x, int y, int inDir, byte[] map, int width, int height, Stack <Point> spread, ushort pattern, bool floorMode)
        {
            PatternReplaceCount filled = new PatternReplaceCount(false);
            var wall = walls[x + y * width];

            if ((wall.Segments & WallSegments.HorizontalDiag) > 0 && (wall.TopRightStyle == 1 || floorMode))
            {
                if (inDir < 2)
                {
                    //bottom (bottom right pattern)
                    if (!floorMode && wall.BottomLeftPattern != pattern)
                    {
                        filled.Add(wall.BottomLeftPattern);
                        wall.BottomLeftPattern = pattern;
                    }
                    map[x + y * width] |= 1;
                }
                else
                {
                    //top (bottom left pattern)
                    if (!floorMode && wall.BottomRightPattern != pattern)
                    {
                        filled.Add(wall.BottomRightPattern);
                        wall.BottomRightPattern = pattern;
                    }
                    map[x + y * width] |= 2;
                }
                if (!floorMode)
                {
                    walls[x + y * width] = wall;
                }
            }
            else if ((wall.Segments & WallSegments.VerticalDiag) > 0 && (wall.TopRightStyle == 1 || floorMode))
            {
                if (inDir > 0 && inDir < 3)
                {
                    //left
                    if (!floorMode && wall.BottomRightPattern != pattern)
                    {
                        filled.Add(wall.BottomRightPattern);
                        wall.BottomRightPattern = pattern;
                    }
                    map[x + y * width] |= 1;
                }
                else
                {
                    //right
                    if (!floorMode && wall.BottomLeftPattern != pattern)
                    {
                        filled.Add(wall.BottomLeftPattern);
                        wall.BottomLeftPattern = pattern;
                    }
                    map[x + y * width] |= 2;
                }
                if (!floorMode)
                {
                    walls[x + y * width] = wall;
                }
            }
            else
            {
                map[x + y * width] = 3;
            }

            spread.Push(new Point(x, y));
            return(filled);
        }
Beispiel #3
0
        /// <summary>
        /// Fills a room with a certain Floor pattern. Returns floors covered
        /// </summary>
        public static PatternReplaceCount FloorPatternFill(VMArchitecture target, Point pos, ushort pattern, sbyte level) //for first floor gen, curRoom should be 1. For floors above, it should be the last genmap result
        {
            if (pattern > 65533 || pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height)
            {
                return(new PatternReplaceCount());
            }

            pos.X = Math.Max(Math.Min(pos.X, target.Width - 1), 0);
            pos.Y = Math.Max(Math.Min(pos.Y, target.Height - 1), 0);
            var walls = target.Walls[level - 1];

            var width  = target.Width;
            var height = target.Height;
            PatternReplaceCount floorsCovered = new PatternReplaceCount(true);

            byte[] Map = new byte[target.Width * target.Height];

            //flood fill recursively. Each time choose find and choose the first "0" as the base.
            //The first recursion (outside) cannot fill into diagonals.
            var spread = new Stack <Point>();

            spread.Push(pos);
            while (spread.Count > 0)
            {
                var item = spread.Pop();

                var plusX = (item.X + 1) % width;
                var minX  = (item.X + width - 1) % width;
                var plusY = (item.Y + 1) % height;
                var minY  = (item.Y + height - 1) % height;

                var mainWalls = walls[item.X + item.Y * width];
                var floor     = target.GetFloor((short)item.X, (short)item.Y, level);
                if ((byte)mainWalls.Segments > 15)
                {
                    //draw floor onto a diagonal;
                    var  wall  = walls[item.X + item.Y * width];
                    byte flags = Map[item.X + item.Y * width];

                    if (flags == 3)
                    {
                        continue;
                    }
                    if ((mainWalls.Segments & WallSegments.HorizontalDiag) > 0)
                    {
                        flags = (byte)(3 - flags);
                    }

                    if ((flags & 1) == 1 && wall.TopLeftPattern != pattern)
                    {
                        floorsCovered.Add(wall.TopLeftPattern);
                        wall.TopLeftPattern = pattern;
                    }
                    else if ((flags & 2) == 2 && wall.TopLeftStyle != pattern)
                    {
                        floorsCovered.Add(wall.TopLeftStyle);
                        wall.TopLeftStyle = pattern;
                    }

                    walls[item.X + item.Y * width] = wall;
                    continue; //don't spread on diagonals for now
                }
                else
                {
                    //normal tile, draw a floor here.
                    if (floor.Pattern != pattern)
                    {
                        var old = floor.Pattern;
                        floor.Pattern = pattern;
                        if (target.SetFloor((short)item.X, (short)item.Y, level, floor, false))
                        {
                            floorsCovered.DAdd(old);
                        }
                    }
                }

                if (Map[plusX + item.Y * width] < 3 && (mainWalls.Segments & WallSegments.BottomRight) == 0)
                {
                    SpreadOnto(walls, plusX, item.Y, 0, Map, width, height, spread, pattern, true);
                }

                if (Map[minX + item.Y * width] < 3 && (mainWalls.Segments & WallSegments.TopLeft) == 0)
                {
                    SpreadOnto(walls, minX, item.Y, 2, Map, width, height, spread, pattern, true);
                }

                if (Map[item.X + plusY * width] < 3 && (mainWalls.Segments & WallSegments.BottomLeft) == 0)
                {
                    SpreadOnto(walls, item.X, plusY, 1, Map, width, height, spread, pattern, true);
                }

                if (Map[item.X + minY * width] < 3 && (mainWalls.Segments & WallSegments.TopRight) == 0)
                {
                    SpreadOnto(walls, item.X, minY, 3, Map, width, height, spread, pattern, true);
                }

                walls[item.X + item.Y * width] = mainWalls;
            }
            return(floorsCovered);
        }
Beispiel #4
0
        public static PatternReplaceCount WallPatternDot(VMArchitecture target, Point pos, ushort pattern, int direction, int altDir, sbyte level)
        {
            if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y > target.Height)
            {
                return new PatternReplaceCount {
                           Total = -1
                }
            }
            ;

            //pattern replace count used a little differently here. cost still stores replaced cost, but total stores replaced direction.
            PatternReplaceCount replaceCost = new PatternReplaceCount(false);
            ushort replaced = 0;
            var    wall     = target.GetWall((short)pos.X, (short)pos.Y, level);

            //direction starts lefttop, righttop
            if ((wall.Segments & WallSegments.HorizontalDiag) > 0 && wall.TopRightStyle == 1)
            {
                if (direction < 2)
                {
                    //bottom (bottom right pattern)
                    replaced = wall.BottomRightPattern;
                    wall.BottomRightPattern = pattern;
                }
                else
                {
                    //top (bottom left pattern)
                    replaced = wall.BottomLeftPattern;
                    wall.BottomLeftPattern = pattern;
                }
                target.SetWall((short)pos.X, (short)pos.Y, level, wall);

                if (replaced == pattern)
                {
                    return new PatternReplaceCount {
                               Total = -1
                    }
                }
                ;
                replaceCost.Add(replaced);
                replaceCost.Total = direction;
                return(replaceCost);
            }
            else if ((wall.Segments & WallSegments.VerticalDiag) > 0 && wall.TopRightStyle == 1)
            {
                if (direction > 0 && direction < 3)
                {
                    //left
                    replaced = wall.BottomLeftPattern;

                    wall.BottomLeftPattern = pattern;
                }
                else
                {
                    //right
                    replaced = wall.BottomRightPattern;
                    wall.BottomRightPattern = pattern;
                }
                target.SetWall((short)pos.X, (short)pos.Y, level, wall);
                if (replaced == pattern)
                {
                    return new PatternReplaceCount {
                               Total = -1
                    }
                }
                ;
                replaceCost.Add(replaced);
                replaceCost.Total = direction;
                return(replaceCost);
            }

            if ((wall.Segments & (WallSegments)(1 << direction)) > 0)
            {
            }
            else if ((wall.Segments & (WallSegments)(1 << altDir)) > 0)
            {
                direction = altDir;
            }
            else
            {
                return(new PatternReplaceCount {
                    Total = -1
                });
            }

            if (direction == 0 && wall.TopLeftThick)
            {
                replaced = wall.TopLeftPattern; wall.TopLeftPattern = pattern;
            }
            else if (direction == 1 && wall.TopRightThick)
            {
                replaced = wall.TopRightPattern; wall.TopRightPattern = pattern;
            }
            else if (direction == 2 && pos.X < target.Width && target.GetWall((short)(pos.X + 1), (short)pos.Y, level).TopLeftThick)
            {
                replaced = wall.BottomRightPattern; wall.BottomRightPattern = pattern;
            }
            else if (direction == 3 && pos.Y < target.Height && target.GetWall((short)pos.X, (short)(pos.Y + 1), level).TopRightThick)
            {
                replaced = wall.BottomLeftPattern; wall.BottomLeftPattern = pattern;
            }
            target.SetWall((short)pos.X, (short)pos.Y, level, wall);

            if (replaced == pattern)
            {
                return new PatternReplaceCount {
                           Total = -1
                }
            }
            ;
            replaceCost.Add(replaced);
            replaceCost.Total = direction;
            return(replaceCost);
        }
Beispiel #5
0
        /// <summary>
        /// Fills a room with a certain wall pattern. Returns walls covered
        /// </summary>
        public static PatternReplaceCount WallPatternFill(VMArchitecture target, Point pos, ushort pattern, sbyte level) //for first floor gen, curRoom should be 1. For floors above, it should be the last genmap result
        {
            if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height)
            {
                return(new PatternReplaceCount());
            }

            pos.X = Math.Max(Math.Min(pos.X, target.Width - 1), 0);
            pos.Y = Math.Max(Math.Min(pos.Y, target.Height - 1), 0);
            var walls = target.Walls[level - 1];

            var width  = target.Width;
            var height = target.Height;
            PatternReplaceCount wallsCovered = new PatternReplaceCount(false);

            byte[] Map = new byte[target.Width * target.Height];

            //flood fill recursively. Each time choose find and choose the first "0" as the base.
            //The first recursion (outside) cannot fill into diagonals.
            var spread = new Stack <Point>();

            spread.Push(pos);
            while (spread.Count > 0)
            {
                var item = spread.Pop();

                var plusX = (item.X + 1) % width;
                var minX  = (item.X + width - 1) % width;
                var plusY = (item.Y + 1) % height;
                var minY  = (item.Y + height - 1) % height;

                var mainWalls = walls[item.X + item.Y * width];
                if ((byte)mainWalls.Segments > 15)
                {
                    continue;                                //don't spread on diagonals for now
                }
                var PXWalls = walls[plusX + item.Y * width];
                var PYWalls = walls[item.X + plusY * width];

                if (Map[plusX + item.Y * width] < 3 && ((PXWalls.Segments & WallSegments.TopLeft) == 0 || PXWalls.TopLeftStyle != 1))
                {
                    wallsCovered += SpreadOnto(walls, plusX, item.Y, 0, Map, width, height, spread, pattern, false);
                }
                else
                {
                    if (mainWalls.BottomRightPattern != pattern && PXWalls.TopLeftThick)
                    {
                        wallsCovered.Add(mainWalls.BottomRightPattern);
                        mainWalls.BottomRightPattern = pattern;
                    }
                }

                if (Map[minX + item.Y * width] < 3 && ((mainWalls.Segments & WallSegments.TopLeft) == 0 || mainWalls.TopLeftStyle != 1))
                {
                    wallsCovered += SpreadOnto(walls, minX, item.Y, 2, Map, width, height, spread, pattern, false);
                }
                else
                {
                    if (mainWalls.TopLeftPattern != pattern && mainWalls.TopLeftThick)
                    {
                        wallsCovered.Add(mainWalls.TopLeftPattern);;
                        mainWalls.TopLeftPattern = pattern;
                    }
                }

                if (Map[item.X + plusY * width] < 3 && ((PYWalls.Segments & WallSegments.TopRight) == 0 || PYWalls.TopRightStyle != 1))
                {
                    wallsCovered += SpreadOnto(walls, item.X, plusY, 1, Map, width, height, spread, pattern, false);
                }
                else
                {
                    if (mainWalls.BottomLeftPattern != pattern && PYWalls.TopRightThick)
                    {
                        wallsCovered.Add(mainWalls.BottomLeftPattern);
                        mainWalls.BottomLeftPattern = pattern;
                    }
                }

                if (Map[item.X + minY * width] < 3 && ((mainWalls.Segments & WallSegments.TopRight) == 0 || mainWalls.TopRightStyle != 1))
                {
                    wallsCovered += SpreadOnto(walls, item.X, minY, 3, Map, width, height, spread, pattern, false);
                }
                else
                {
                    if (mainWalls.TopRightPattern != pattern && mainWalls.TopRightThick)
                    {
                        wallsCovered.Add(mainWalls.TopRightPattern);
                        mainWalls.TopRightPattern = pattern;
                    }
                }

                walls[item.X + item.Y * width] = mainWalls;
            }
            return(wallsCovered);
        }
        private static PatternReplaceCount SpreadOnto(WallTile[] walls, int x, int y, int inDir, byte[] map, int width, int height, Stack<Point> spread, ushort pattern, bool floorMode)
        {
            PatternReplaceCount filled = new PatternReplaceCount(false);
            var wall = walls[x + y * width];
            if ((wall.Segments & WallSegments.HorizontalDiag) > 0 && (wall.TopRightStyle == 1 || floorMode))
            {
                if (inDir < 2)
                {
                    //bottom (bottom right pattern)
                    if (!floorMode && wall.BottomLeftPattern != pattern)
                    {
                        filled.Add(wall.BottomLeftPattern);
                        wall.BottomLeftPattern = pattern;
                    }
                    map[x + y * width] |= 1;
                } else
                {
                    //top (bottom left pattern)
                    if (!floorMode && wall.BottomRightPattern != pattern)
                    {
                        filled.Add(wall.BottomRightPattern);
                        wall.BottomRightPattern = pattern;
                    }
                    map[x + y * width] |= 2;
                }
                if (!floorMode) walls[x + y * width] = wall;
            }
            else if ((wall.Segments & WallSegments.VerticalDiag) > 0 && (wall.TopRightStyle == 1 || floorMode))
            {
                if (inDir > 0 && inDir < 3)
                {
                    //left
                    if (!floorMode && wall.BottomRightPattern != pattern)
                    {
                        filled.Add(wall.BottomRightPattern);
                        wall.BottomRightPattern = pattern;
                    }
                    map[x + y * width] |= 1;
                }
                else
                {
                    //right
                    if (!floorMode && wall.BottomLeftPattern != pattern)
                    {
                        filled.Add(wall.BottomLeftPattern);
                        wall.BottomLeftPattern = pattern;
                    }
                    map[x + y * width] |= 2;
                }
                if (!floorMode) walls[x + y * width] = wall;
            }
            else
            {
                map[x + y * width] = 3;
            }

            spread.Push(new Point(x, y));
            return filled;
        }
        //for first floor gen, curRoom should be 1. For floors above, it should be the last genmap result
        /// <summary>
        /// Fills a room with a certain wall pattern. Returns walls covered
        /// </summary>
        public static PatternReplaceCount WallPatternFill(VMArchitecture target, Point pos, ushort pattern, sbyte level)
        {
            if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height) return new PatternReplaceCount();

            pos.X = Math.Max(Math.Min(pos.X, target.Width-1), 0);
            pos.Y = Math.Max(Math.Min(pos.Y, target.Height-1), 0);
            var walls = target.Walls[level-1];

            var width = target.Width;
            var height = target.Height;
            PatternReplaceCount wallsCovered = new PatternReplaceCount(false);

            byte[] Map = new byte[target.Width * target.Height];

            //flood fill recursively. Each time choose find and choose the first "0" as the base.
            //The first recursion (outside) cannot fill into diagonals.
            var spread = new Stack<Point>();
            spread.Push(pos);
            while (spread.Count > 0)
            {
                var item = spread.Pop();

                var plusX = (item.X + 1) % width;
                var minX = (item.X + width - 1) % width;
                var plusY = (item.Y + 1) % height;
                var minY = (item.Y + height - 1) % height;

                var mainWalls = walls[item.X + item.Y * width];
                if ((byte)mainWalls.Segments > 15) continue; //don't spread on diagonals for now

                var PXWalls = walls[plusX + item.Y * width];
                var PYWalls = walls[item.X + plusY * width];

                if (Map[plusX + item.Y * width] < 3 && ((PXWalls.Segments & WallSegments.TopLeft) == 0 || PXWalls.TopLeftStyle != 1))
                    wallsCovered += SpreadOnto(walls, plusX, item.Y, 0, Map, width, height, spread, pattern, false);
                else
                {
                    if (mainWalls.BottomRightPattern != pattern && PXWalls.TopLeftThick)
                    {
                        wallsCovered.Add(mainWalls.BottomRightPattern);
                        mainWalls.BottomRightPattern = pattern;
                    }
                }

                if (Map[minX + item.Y * width]<3 && ((mainWalls.Segments & WallSegments.TopLeft) == 0 || mainWalls.TopLeftStyle != 1))
                    wallsCovered += SpreadOnto(walls, minX, item.Y, 2, Map, width, height, spread, pattern, false);
                else
                {
                    if (mainWalls.TopLeftPattern != pattern && mainWalls.TopLeftThick)
                    {
                        wallsCovered.Add(mainWalls.TopLeftPattern); ;
                        mainWalls.TopLeftPattern = pattern;
                    }
                }

                if (Map[item.X + plusY * width]<3 && ((PYWalls.Segments & WallSegments.TopRight) == 0 || PYWalls.TopRightStyle != 1))
                    wallsCovered += SpreadOnto(walls, item.X, plusY, 1, Map, width, height, spread, pattern, false);
                else
                {
                    if (mainWalls.BottomLeftPattern != pattern && PYWalls.TopRightThick)
                    {
                        wallsCovered.Add(mainWalls.BottomLeftPattern);
                        mainWalls.BottomLeftPattern = pattern;
                    }
                }

                if (Map[item.X + minY * width]<3 && ((mainWalls.Segments & WallSegments.TopRight) == 0 || mainWalls.TopRightStyle != 1))
                    wallsCovered += SpreadOnto(walls, item.X, minY, 3, Map, width, height, spread, pattern, false);
                else
                {
                    if (mainWalls.TopRightPattern != pattern && mainWalls.TopRightThick)
                    {
                        wallsCovered.Add(mainWalls.TopRightPattern);
                        mainWalls.TopRightPattern = pattern;
                    }
                }

                walls[item.X + item.Y * width] = mainWalls;
            }
            return wallsCovered;
        }
        public static PatternReplaceCount WallPatternDot(VMArchitecture target, Point pos, ushort pattern, int direction, int altDir, sbyte level)
        {
            if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y > target.Height) return new PatternReplaceCount { Total = -1 };

            //pattern replace count used a little differently here. cost still stores replaced cost, but total stores replaced direction.
            PatternReplaceCount replaceCost = new PatternReplaceCount(false);
            ushort replaced = 0;
            var wall = target.GetWall((short)pos.X, (short)pos.Y, level);
            //direction starts lefttop, righttop
            if ((wall.Segments & WallSegments.HorizontalDiag) > 0 && wall.TopRightStyle == 1)
            {
                if (direction < 2)
                {
                    //bottom (bottom right pattern)
                    replaced = wall.BottomRightPattern;
                    wall.BottomRightPattern = pattern;
                }
                else
                {
                    //top (bottom left pattern)
                    replaced = wall.BottomLeftPattern;
                    wall.BottomLeftPattern = pattern;
                }
                target.SetWall((short)pos.X, (short)pos.Y, level, wall);
                if (replaced == pattern) return new PatternReplaceCount { Total = -1 };
                replaceCost.Add(replaced);
                replaceCost.Total = direction;
                return replaceCost;
            }
            else if ((wall.Segments & WallSegments.VerticalDiag) > 0 && wall.TopRightStyle == 1)
            {
                if (direction > 0 && direction < 3)
                {
                    //left
                    replaced = wall.BottomLeftPattern;
                    wall.BottomLeftPattern = pattern;
                }
                else
                {
                    //right
                    replaced = wall.BottomRightPattern;
                    wall.BottomRightPattern = pattern;
                }
                target.SetWall((short)pos.X, (short)pos.Y, level, wall);
                if (replaced == pattern) return new PatternReplaceCount { Total = -1 };
                replaceCost.Add(replaced);
                replaceCost.Total = direction;
                return replaceCost;
            }

            if ((wall.Segments & (WallSegments)(1 << direction)) > 0) { }
            else if ((wall.Segments & (WallSegments)(1 << altDir)) > 0) direction = altDir;
            else
            {
                return new PatternReplaceCount { Total = -1 };
            }

            if (direction == 0 && wall.TopLeftThick) { replaced = wall.TopLeftPattern; wall.TopLeftPattern = pattern; }
            else if (direction == 1 && wall.TopRightThick) { replaced = wall.TopRightPattern; wall.TopRightPattern = pattern; }
            else if (direction == 2 && pos.X < target.Width && target.GetWall((short)(pos.X + 1), (short)pos.Y, level).TopLeftThick) { replaced = wall.BottomRightPattern; wall.BottomRightPattern = pattern; }
            else if (direction == 3 && pos.Y < target.Height && target.GetWall((short)pos.X, (short)(pos.Y + 1), level).TopRightThick) { replaced = wall.BottomLeftPattern; wall.BottomLeftPattern = pattern; }
            target.SetWall((short)pos.X, (short)pos.Y, level, wall);

            if (replaced == pattern) return new PatternReplaceCount { Total = -1 };
            replaceCost.Add(replaced);
            replaceCost.Total = direction;
            return replaceCost;
        }
        //returns floors covered
        public static PatternReplaceCount FloorPatternRect(VMArchitecture target, Rectangle rect, ushort dir, ushort pattern, sbyte level)
        {
            PatternReplaceCount floorsCovered = new PatternReplaceCount(true);
            if (rect.Width == 0 && rect.Height == 0)
            {
                //dot mode, just fill a tile. can be a diagonal.
                if (rect.X < 0 || rect.X >= target.Width || rect.Y < 0 || rect.Y >= target.Width) return floorsCovered;
                var wall = target.GetWall((short)rect.X, (short)rect.Y, level);
                if ((wall.Segments & AnyDiag) > 0 && pattern < 65534)
                {
                    bool side = ((wall.Segments & WallSegments.HorizontalDiag) > 0) ? (dir < 2) : (dir < 1 || dir > 2);
                    if (side)
                    {
                        if (wall.TopLeftStyle != pattern)
                        {
                            floorsCovered.Add(wall.TopLeftStyle);
                            wall.TopLeftStyle = pattern;
                        }
                    }
                    else
                    {
                        if (wall.TopLeftPattern != pattern)
                        {
                            floorsCovered.Add(wall.TopLeftPattern);
                            wall.TopLeftPattern = pattern;
                        }
                    }
                    target.SetWall((short)rect.X, (short)rect.Y, level, wall);
                }
                else if ((wall.Segments & AnyDiag) == 0)
                {
                    var floor = target.GetFloor((short)rect.X, (short)rect.Y, level);
                    if (floor.Pattern != pattern)
                    {
                        var old = floor.Pattern;
                        floor.Pattern = pattern;
                        if (target.SetFloor((short)rect.X, (short)rect.Y, level, floor, false)) floorsCovered.DAdd(old);
                    }
                }
                return floorsCovered;
            }

            var xEnd = Math.Min(target.Width, rect.X + rect.Width+1);
            var yEnd = Math.Min(target.Height, rect.Y + rect.Height+1);
            for (int y = Math.Max(0, rect.Y); y < yEnd; y++)
            {
                for (int x = Math.Max(0, rect.X); x < xEnd; x++)
                {
                    var wall = target.GetWall((short)x, (short)y, level);
                    if ((wall.Segments & AnyDiag) > 0) //diagonal floors are stored in walls
                    {
                        if (pattern < 65534) continue;
                        if (wall.TopLeftStyle != pattern)
                        {
                            wall.TopLeftStyle = pattern;
                            floorsCovered.Add(wall.TopLeftStyle);
                        }

                        if (wall.TopLeftPattern != pattern)
                        {
                            wall.TopLeftPattern = pattern;
                            floorsCovered.Add(wall.TopLeftPattern);
                        }
                        target.SetWall((short)x, (short)y, level, wall);
                    }
                    else
                    {
                        var floor = target.GetFloor((short)x, (short)y, level);
                        if (floor.Pattern != pattern)
                        {
                            var old = floor.Pattern;
                            floor.Pattern = pattern;
                            if (target.SetFloor((short)x, (short)y, level, floor, false)) floorsCovered.DAdd(old);
                        }
                    }
                }
            }
            return floorsCovered;
        }
        //for first floor gen, curRoom should be 1. For floors above, it should be the last genmap result
        /// <summary>
        /// Fills a room with a certain Floor pattern. Returns floors covered
        /// </summary>
        public static PatternReplaceCount FloorPatternFill(VMArchitecture target, Point pos, ushort pattern, sbyte level)
        {
            if (pattern > 65533 || pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height) return new PatternReplaceCount();

            pos.X = Math.Max(Math.Min(pos.X, target.Width - 1), 0);
            pos.Y = Math.Max(Math.Min(pos.Y, target.Height - 1), 0);
            var walls = target.Walls[level-1];

            var width = target.Width;
            var height = target.Height;
            PatternReplaceCount floorsCovered = new PatternReplaceCount(true);

            byte[] Map = new byte[target.Width * target.Height];

            //flood fill recursively. Each time choose find and choose the first "0" as the base.
            //The first recursion (outside) cannot fill into diagonals.
            var spread = new Stack<Point>();
            spread.Push(pos);
            while (spread.Count > 0)
            {
                var item = spread.Pop();

                var plusX = (item.X + 1) % width;
                var minX = (item.X + width - 1) % width;
                var plusY = (item.Y + 1) % height;
                var minY = (item.Y + height - 1) % height;

                var mainWalls = walls[item.X + item.Y * width];
                var floor = target.GetFloor((short)item.X, (short)item.Y, level);
                if ((byte)mainWalls.Segments > 15)
                {
                    //draw floor onto a diagonal;
                    var wall = walls[item.X + item.Y * width];
                    byte flags = Map[item.X + item.Y * width];

                    if (flags == 3) continue;
                    if ((mainWalls.Segments & WallSegments.HorizontalDiag) > 0) flags = (byte)(3 - flags);

                        if ((flags & 1) == 1 && wall.TopLeftPattern != pattern)
                        {
                            floorsCovered.Add(wall.TopLeftPattern);
                            wall.TopLeftPattern = pattern;
                        }
                        else if ((flags & 2) == 2 && wall.TopLeftStyle != pattern)
                        {
                            floorsCovered.Add(wall.TopLeftStyle);
                            wall.TopLeftStyle = pattern;
                        }

                    walls[item.X + item.Y * width] = wall;
                    continue; //don't spread on diagonals for now
                }
                else
                {
                    //normal tile, draw a floor here.
                    if (floor.Pattern != pattern)
                    {
                        var old = floor.Pattern;
                        floor.Pattern = pattern;
                        if (target.SetFloor((short)item.X, (short)item.Y, level, floor, false)) floorsCovered.DAdd(old);
                    }
                }

                if (Map[plusX + item.Y * width] < 3 && (mainWalls.Segments & WallSegments.BottomRight) == 0)
                    SpreadOnto(walls, plusX, item.Y, 0, Map, width, height, spread, pattern, true);

                if (Map[minX + item.Y * width] < 3 && (mainWalls.Segments & WallSegments.TopLeft) == 0)
                    SpreadOnto(walls, minX, item.Y, 2, Map, width, height, spread, pattern, true);

                if (Map[item.X + plusY * width] < 3 && (mainWalls.Segments & WallSegments.BottomLeft) == 0)
                    SpreadOnto(walls, item.X, plusY, 1, Map, width, height, spread, pattern, true);

                if (Map[item.X + minY * width] < 3 && (mainWalls.Segments & WallSegments.TopRight) == 0)
                    SpreadOnto(walls, item.X, minY, 3, Map, width, height, spread, pattern, true);

                walls[item.X + item.Y * width] = mainWalls;
            }
            return floorsCovered;
        }