private Rect CreateRectRoom(int width, int height, bool firstRoom = false)
        {
            int x, y;

            // Position the room
            if (firstRoom)
            {
                // Initial room, so start near center
                x = Rng.TriangleInt((_writer.Bounds.Width - width) / 2, (_writer.Bounds.Width - width) / 2 - 4);
                y = Rng.TriangleInt((_writer.Bounds.Height - height) / 2, (_writer.Bounds.Height - height) / 2 - 4);
            }
            else
            {
                // Place it wherever
                x = Rng.Int(_writer.Bounds.Width);
                y = Rng.Int(_writer.Bounds.Height);
            }

            Rect bounds = new Rect(x, y, width, height);

            // Check to see if the room can be positioned
            if (!_writer.IsOpen(bounds.Inflate(1), null))
            {
                return(Rect.Empty);
            }

            return(bounds);
        }
Пример #2
0
        /// <summary>
        /// Gets whether the given rectangle is empty (i.e. solid stone) and can have a feature placed in it.
        /// </summary>
        /// <param name="rect">The rectangle to test.</param>
        /// <param name="exception">An optional exception position. If this position is not stone, it is still possible
        /// to use the rect. Used for the connector to a new feature.</param>
        /// <remarks>It tests this by verifying each tile within the rect is a stone square. Originally only traced
        /// the perimeter, but that was allowing rooms to fully enclose other rooms.</remarks>
        public bool IsOpen(Rect rect, Vec2?exception)
        {
            // must be totally in bounds
            if (!_map.Bounds.Contains(rect))
            {
                return(false);
            }

            // and not cover an existing feature
            foreach (Vec2 tile in rect)
            {
                // allow the exception
                if (exception != null && (exception == tile))
                {
                    continue;
                }

                if (_map.Tiles[tile].Type != Tiles.Stone)
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #3
0
 public void TestEnumerateColumn()
 {
     TestEnumeration(Rect.Column(4, 5, 3),
                     new Vec2(4, 5),
                     new Vec2(4, 6),
                     new Vec2(4, 7));
 }
Пример #4
0
 public void TestEnumerateRow()
 {
     TestEnumeration(Rect.Row(4, 5, 3),
                     new Vec2(4, 5),
                     new Vec2(5, 5),
                     new Vec2(6, 5));
 }
Пример #5
0
        public void TestRow()
        {
            Rect r = Rect.Row(4);

            Assert.AreEqual(0, r.Position.x);
            Assert.AreEqual(0, r.Position.y);
            Assert.AreEqual(4, r.Size.x);
            Assert.AreEqual(1, r.Size.y);
        }
Пример #6
0
        public void TestConstructorPositionIntSizeVec()
        {
            Rect r = new Rect(2, 4, new Vec2(3, 5));

            Assert.AreEqual(2, r.Position.x);
            Assert.AreEqual(4, r.Position.y);
            Assert.AreEqual(3, r.Size.x);
            Assert.AreEqual(5, r.Size.y);
        }
Пример #7
0
        public void TestColumn()
        {
            Rect r = Rect.Column(4);

            Assert.AreEqual(0, r.Position.x);
            Assert.AreEqual(0, r.Position.y);
            Assert.AreEqual(1, r.Size.x);
            Assert.AreEqual(4, r.Size.y);
        }
Пример #8
0
        public void TestRowPos()
        {
            Rect r = Rect.Row(-2, 3, 4);

            Assert.AreEqual(-2, r.Position.x);
            Assert.AreEqual(3, r.Position.y);
            Assert.AreEqual(4, r.Size.x);
            Assert.AreEqual(1, r.Size.y);
        }
Пример #9
0
        public void TestConstructorDefault()
        {
            Rect r = new Rect();

            Assert.AreEqual(0, r.Position.x);
            Assert.AreEqual(0, r.Position.y);
            Assert.AreEqual(0, r.Size.x);
            Assert.AreEqual(0, r.Size.y);
        }
Пример #10
0
        public void TestConstructorPositionVecSizeInt()
        {
            Rect r = new Rect(new Vec2(2, 4), 3, 5);

            Assert.AreEqual(2, r.Position.x);
            Assert.AreEqual(4, r.Position.y);
            Assert.AreEqual(3, r.Size.x);
            Assert.AreEqual(5, r.Size.y);
        }
Пример #11
0
        public void TestColumnVecPos()
        {
            Rect r = Rect.Column(new Vec2(-2, 3), 4);

            Assert.AreEqual(-2, r.Position.x);
            Assert.AreEqual(3, r.Position.y);
            Assert.AreEqual(1, r.Size.x);
            Assert.AreEqual(4, r.Size.y);
        }
Пример #12
0
        public void TestEmpty()
        {
            Rect r = Rect.Empty;

            Assert.AreEqual(0, r.Position.x);
            Assert.AreEqual(0, r.Position.y);
            Assert.AreEqual(0, r.Size.x);
            Assert.AreEqual(0, r.Size.x);
        }
Пример #13
0
        public void TestConstructorSizeVec()
        {
            Rect r = new Rect(new Vec2(3, 5));

            Assert.AreEqual(0, r.Position.x);
            Assert.AreEqual(0, r.Position.y);
            Assert.AreEqual(3, r.Size.x);
            Assert.AreEqual(5, r.Size.y);
        }
        public bool CreateFeature(string name, out Rect bounds)
        {
            switch (name)
            {
            case "room":
                return(MakeRoom(out bounds));

            default: throw new ArgumentException($"Unknown feature \"{name}\"");
            }
        }
        private void Populate(Rect bounds, int monsterDensity, int itemDensity)
        {
            // TODO: For testing, place one NPC in each room. For real this should probably be more random!
            //foreach (Rect room in _rooms)
            {
                int xOffset = Rng.Int(bounds.Width);
                int yOffset = Rng.Int(bounds.Height);

                Vec2 location = bounds.Position + new Vec2(xOffset, yOffset);

                _writer.Populate(location);
            }
        }
        private Rect CreateRoom(bool startingRoom = false)
        {
            int width  = Rng.Int(_writer.Options.RoomSizeMin, _writer.Options.RoomSizeMax);
            int height = Rng.Int(_writer.Options.RoomSizeMin, _writer.Options.RoomSizeMax);

            Rect bounds = CreateRectRoom(width, height, startingRoom);

            // Bail if we failed
            if (bounds == Rect.Empty)
            {
                return(bounds);
            }

            // Place the room
            foreach (Vec2 position in bounds)
            {
                _writer.SetTile(position, Tiles.Floor);
            }

            // And the walls surrounding the room
            foreach (Vec2 position in bounds.Trace())
            {
                _writer.SetTile(position, Tiles.Wall);
            }

            // === Room decoration code here ===
            //TileType decoration = ChooseInnerWall();

            //RoomDecoration.Decorate(bounds, new RoomDecorator(this, position => _writer.Populate(position, 60, 200)));

            //_writer.LightRect(bounds);

            // place the connectors
            //AddRoomConnectors(bounds);

            Populate(bounds, 20, 20);
            // === End room decoration code ===

            _rooms.Add(bounds);
            return(bounds);
        }
Пример #17
0
        public void TestCoordinates()
        {
            Rect rect = new Rect(1, 2, 3, 4);

            // x, y
            Assert.AreEqual(1, rect.x);
            Assert.AreEqual(2, rect.y);

            // size
            Assert.AreEqual(3, rect.Width);
            Assert.AreEqual(4, rect.Height);

            // ltrb
            Assert.AreEqual(1, rect.Left);
            Assert.AreEqual(2, rect.Top);
            Assert.AreEqual(1 + 3, rect.Right);
            Assert.AreEqual(2 + 4, rect.Bottom);

            // ltrb vecs
            Assert.AreEqual(new Vec2(1, 2), rect.TopLeft);
            Assert.AreEqual(new Vec2(1 + 3, 2), rect.TopRight);
            Assert.AreEqual(new Vec2(1, 2 + 4), rect.BottomLeft);
            Assert.AreEqual(new Vec2(1 + 3, 2 + 4), rect.BottomRight);
        }
 private bool MakeRoom(out Rect bounds)
 {
     bounds = CreateRoom();
     return(bounds != Rect.Empty);
 }
        public bool MakeHalls()
        {
            List <Vertex> vertices = new List <Vertex>();

            // add a vertex at the center of each room
            foreach (Rect room in _rooms)
            {
                vertices.Add(new Vertex <Rect>(new Vector2(room.Center.x, room.Center.y), room));
            }

            // Create a Delaunay triangulation of the rooms
            _delaunay = Delaunay2D.Triangulate(vertices);

            // Convert the Delaunay edges to Prim edges
            List <Prim.Edge> edges = new List <Prim.Edge>();

            foreach (Delaunay2D.Edge edge in _delaunay.Edges)
            {
                edges.Add(new Prim.Edge(edge.U, edge.V));
            }

            // Create a minimum spanning tree of the triangulation
            List <Prim.Edge> mst = Prim.MinimumSpanningTree(edges, edges[0].U);

            // Get the edges not part of the MST
            HashSet <Prim.Edge> selectedEdges  = new HashSet <Prim.Edge>(mst);
            HashSet <Prim.Edge> remainingEdges = new HashSet <Prim.Edge>(edges);

            remainingEdges.ExceptWith(selectedEdges);

            // Create some loops, since MSTs make for boring maps
            foreach (Prim.Edge edge in remainingEdges)
            {
                if (Rng.Int(100) < _writer.Options.ChanceOfExtraHallway)
                {
                    selectedEdges.Add(edge);
                }
            }

            // Drive a pathfinder to carve out the halls
            Motility motility = Motility.FourWayNeighbors | Motility.Unconstrained;

            foreach (Prim.Edge edge in selectedEdges)
            {
                Rect startRoom = (edge.U as Vertex <Rect>).Item;
                Rect endRoom   = (edge.V as Vertex <Rect>).Item;

                GridNode start = _writer.GetTile(new Vec2(startRoom.Center.x, startRoom.Center.y));
                GridNode goal  = _writer.GetTile(new Vec2(endRoom.Center.x, endRoom.Center.y));

                // Heuristic is Manhattan distance on a square grid
                IList <GridNode> path = _writer.Graph.FindPath <AStarSearchAlgorithm>(start, goal,
                                                                                      motility, (a, b) =>
                                                                                      Math.Abs((float)(a.Position.x - b.Position.x)) + Math.Abs((float)(a.Position.y - b.Position.y)));

                // Bail if the pathfinder failed to find a path (NOTE: if it does, it seems like it should be a problem)
                if (path == null)
                {
                    continue;
                }
                foreach (GridNode step in path)
                {
                    _writer.SetTile(step.Position, Tiles.Floor);
                    foreach (GridNode neighbor in step.Neighbors)
                    {
                        if ((_writer.GetTile(neighbor.Position)).Type == Tiles.Stone)
                        {
                            _writer.SetTile(neighbor.Position, Tiles.Wall);
                        }
                    }
                }
            }

            return(true);
        }