示例#1
0
        /// <summary>
        /// Generate a dungeon in the given map, from the objects in the lists given in the constructor
        /// </summary>
        /// <param name="map">the map to generate the dungeon in</param>
        public void GenerateMap(Map map)
        {
            Logger.Info($"Generation for map size {map.XSize}x{map.YSize}");
            operationCount = 0;
            List <PatternPosition> availablesExits = new List <PatternPosition>();
            List <PatternPosition> usedRooms       = new List <PatternPosition>();

            // get a random entry
            PatternPosition entry = generateEntry(map, _doors);

            GenerateMap(map, entry);
        }
示例#2
0
        /// <summary>
        ///Generate a random entry to be placed on the map
        /// </summary>
        /// <param name="map">the map where the entry would be placed</param>
        /// <param name="doors">the list of available door type</param>
        /// <returns>a position & door type</returns>
        private PatternPosition generateEntry(Map map, MapTemplateList doors)
        {
            MapTemplate     door  = doors.getTemplate(rnd.Next(doors.Count()));
            PatternPosition entry = new PatternPosition();

            entry.y  = rnd.Next(1, map.XSize);
            entry.x  = rnd.Next(1, map.YSize);
            entry.id = door.Id;
            Logger.Info($"Putting Entry door type {door.Id} at {entry.x}x{entry.y}");

            return(entry);
        }
示例#3
0
        /// <summary>
        /// Place a room on the map.
        /// Add the exits of the room to the list of available exits for the map generations, if needed
        /// </summary>
        /// <param name="room"></param>
        /// <param name="xpos"></param>
        /// <param name="ypos"></param>
        /// <param name="availablesExits"></param>
        /// <param name="usedRooms"></param>
        /// <returns>true</returns>
        private bool PlaceRoom(Map map, MapTemplate room, int xpos, int ypos, List <PatternPosition> availablesExits, List <PatternPosition> usedRooms)
        {
            Logger.Info($"placement of {room.Id} at {xpos}x{ypos}", Logger.LogAction.PUSH);
            // put the content of the room on the map.
            for (int y1 = 0; y1 < room.YSize; y1++)
            {
                for (int x1 = 0; x1 < room.XSize; x1++)
                {
                    if (room.Content[y1, x1] != '?')
                    {
                        map.Content[ypos + y1, xpos + x1] = room.Content[y1, x1];
                    }
                }
            }

            // store the room so that we do not try the same room for one of its own exit
            // (as it may work, as the 2 rooms would be superposed)
            PatternPosition newRoom = new PatternPosition();

            newRoom.x  = xpos;
            newRoom.y  = ypos;
            newRoom.id = room.SourceId;
            usedRooms.Add(newRoom);

            // for  all doors from this room, either add it to the 'available' list, or remove it if allready present
            // (this is a common exit with a previous room, and is now used)
            foreach (MapTemplate doorPattern in _doors)
            {
                //find all occurnece of this kind of doors in the room
                List <Position> doorsList = doorPattern.Matches(room, true);
                doorsList.Shuffle();
                foreach (Position position in doorsList)
                {
                    PatternPosition roomDoor = new PatternPosition();
                    roomDoor.x  = position.X + xpos;
                    roomDoor.y  = position.Y + ypos;
                    roomDoor.id = doorPattern.Id;
                    // if already present in the availables list : common exit with a previous room (remove it),
                    if (availablesExits.FindAll(exit => (roomDoor.x == exit.x && roomDoor.y == exit.y && roomDoor.id == exit.id)).Count > 0)
                    {
                        availablesExits.RemoveAll(exit => (roomDoor.x == exit.x && roomDoor.y == exit.y && roomDoor.id == exit.id));
                    }
                    // otherwise add it
                    else
                    {
                        availablesExits.Add(roomDoor);
                    }
                }
            }
            Logger.Pop();
            return(true);
        }
示例#4
0
        /// <summary>
        /// Generate a dungeon in the given map, from the objects in the lists given in the constructor
        /// </summary>
        /// <param name="map">the map to generate the dungeon in</param>
        /// <param name="entry">the entry (door + position) used to start the dungeon</param>
        public void GenerateMap(Map map, PatternPosition entry)
        {
            List <PatternPosition> availablesExits = new List <PatternPosition>();
            List <PatternPosition> usedRooms       = new List <PatternPosition>();
            List <PatternPosition> rejectedExits   = new List <PatternPosition>();

            // use given entry as the initial entry/door
            map.Place(_doors.Find(entry.id), entry.x, entry.y);
            availablesExits.Add(entry);
            // also add it to the toremove (it will not be used by another room...)
            // since it's the first, it will be the "Up" (see ManageEntries)
            rejectedExits.Add(entry);
            if (Debug)
            {
                CharUtils.saveAsImage($"./assets/map{operationCount++}.png", map.Content);
            }

            // While there are not checked exits
            while (availablesExits.Count > 0)
            {
                // Select one door on the map (random)
                //PatternPosition exit = availablesExits[rnd.Next(0, availablesExits.Count)];

                // Select one door on the map (breadth first)
                PatternPosition exit = availablesExits[0];

                // Select one door on the map (deapth first)
                //PatternPosition exit = availablesExits[availablesExits.Count - 1];

                // try to place a room to this exit
                this.PlaceRoomForDoor(map, exit, availablesExits, usedRooms, rejectedExits);

                if (Debug)
                {
                    CharUtils.saveAsImage($"./assets/map{operationCount++}.png", map.Content);
                }
                Logger.Pop();
            }

            // generate an entry and exit
            ManageEntries(map, rejectedExits);

            // remove unwanted artifacts (not used doors...)
            Clean(map);

            // place some new element / remove some based on pattern
            Decorate(map);


            Logger.Pop();
        }
示例#5
0
        /// <summary>
        /// Select two non used doors and set them as exit of the map;
        /// </summary>
        /// <param name="map">the map to get the entries on</param>
        /// <param name="rejectedExits">list of non used doors</param>
        private void ManageEntries(Map map, List <PatternPosition> rejectedExits)
        {
            // choose the exit
            PatternPosition exitPos = rejectedExits[0];
            // get the template
            MapTemplate door = _doors.Find(exitPos.id);
            // duplicate it and change it
            MapTemplate exit = new MapTemplate(door);

            CharUtils.ReplaceAll(exit.Content, '=', 'U');
            // update the map
            map.Place(exit, exitPos.x, exitPos.y);
            map.UpExit = exitPos;

            exitPos = rejectedExits[rejectedExits.Count - 1];
            // get the template
            door = _doors.Find(exitPos.id);
            // duplicate it and change it
            exit = new MapTemplate(door);
            CharUtils.ReplaceAll(exit.Content, '=', 'D');
            // update the map
            map.Place(exit, exitPos.x, exitPos.y);
            map.DownExit = exitPos;
        }
示例#6
0
        /// <summary>
        /// Try to place a room, given an exit position ( ie door ). The room will be taken in the list of room having this kind of exit.
        /// if a room is placed, new exits will be adde to the list, and old one (common to another room) removed.
        /// </summary>
        /// <param name="exit">the exit position & pattern</param>
        /// <param name="availablesExits">the list of available exit</param>
        /// <returns>true if a room was placed</returns>
        private bool PlaceRoomForDoor(Map map, PatternPosition exit, List <PatternPosition> availablesExits, List <PatternPosition> usedRooms, List <PatternPosition> rejectedExits)
        {
            ;
            MapTemplateList possiblesRooms = doorGroups[exit.id];

            possiblesRooms.collection.Shuffle();
            possiblesRooms.collection.Sort(
                delegate(MapTemplate x,
                         MapTemplate y)
            {
                var xx = x.SortValue - x.Usage;
                var yy = y.SortValue - y.Usage;
                if (xx == yy)
                {
                    return(0);
                }
                if (xx < yy)
                {
                    return(1);
                }
                else
                {
                    return(-1);
                }
            }
                );

            bool placed = false;

            // for all room that contains our exit
            //possiblesRooms.Reset();
            foreach (MapTemplate room in possiblesRooms)
            {
                // get all position in this room of the exi we're working on
                List <Position> possibleExits = _doors.Find(exit.id).Matches(room, true);
                possibleExits.Shuffle();
                foreach (Position pos in possibleExits)
                {
                    // check if the room can be put, mapping the choosen room exit with the exit we were given
                    if (CheckRoom(map, room, exit.x - pos.X, exit.y - pos.Y, usedRooms))
                    {
                        // place the room
                        PlaceRoom(map, room, exit.x - pos.X, exit.y - pos.Y, availablesExits, usedRooms);
                        // change all usage of room with the same SourceId
                        UpdateUsage(room);
                        // flag the map as modified
                        placed = true;
                        break; // leave the search for a valid exit
                    }
                }
                // if a room has been placed onto the exit, leave the search for a room
                if (placed)
                {
                    break;
                }
            }

            // if no room found, remove the exit from the list of available (if placed, this has already be done)
            if (!placed)
            {
                availablesExits.RemoveAll(template => (exit.x == template.x && exit.y == template.y && exit.id == template.id));
                rejectedExits.Add(exit);
            }
            return(placed);
        }