예제 #1
0
        private bool AddMonsterLinearPatrol(MapInfo mapInfo, MonsterFightAndRunAI monster, Dictionary <int, List <int> > terminalBranchNodes, int level)
        {
            var roomsOnLevel = mapInfo.FilterOutCorridors(mapInfo.GetRoomIndicesForLevel(level));

            var roomsWithNeigbours = terminalBranchNodes.Where(tb => tb.Key > 1).SelectMany(tb => tb.Value).Intersect(roomsOnLevel);

            var sourceRooms = roomsWithNeigbours.Shuffle();

            //May be expensive
            Point        startPoint = null;
            List <Point> waypoints  = new List <Point>();

            foreach (var room in sourceRooms)
            {
                var distanceToOtherRooms = mapInfo.Model.GetDistanceOfVerticesFromParticularVertexInFullMap(room, roomsWithNeigbours);

                var sisterRooms = distanceToOtherRooms.Where(kv => kv.Value == 2).Select(kv => kv.Key);

                if (!sisterRooms.Any())
                {
                    continue;
                }

                var candidatePointsInRoom = mapInfo.GetAllPointsInRoomOfTerrain(room, RoomTemplateTerrain.Floor).Shuffle();

                bool success = false;
                foreach (var p in candidatePointsInRoom)
                {
                    success = Game.Dungeon.AddMonster(monster, level, p);

                    if (success)
                    {
                        startPoint = p;
                        break;
                    }
                }

                if (!success)
                {
                    //Failure
                    continue;
                }

                foreach (var sisterRoom in sisterRooms)
                {
                    var candidatePointInSisterRoom = mapInfo.GetAllPointsInRoomOfTerrain(sisterRoom, RoomTemplateTerrain.Floor).RandomElement();
                    waypoints.Add(candidatePointInSisterRoom);
                }

                monster.Waypoints = waypoints;
                break;
            }

            if (startPoint == null)
            {
                return(false);
            }

            return(true);
        }
예제 #2
0
        public void CreateMonstersForLevels(MapInfo mapInfo, int level, int levelDifficulty)
        {
            SetupMonsterWeightings();

            var monsterSetsUsed = new List <MonsterSet>();

            var roomVertices      = mapInfo.FilterOutCorridors(mapInfo.GetRoomIndicesForLevel(level));
            var floorAreaForLevel = roomVertices.Sum(v => mapInfo.GetAllPointsInRoomOfTerrain(v, RoomTemplateTerrain.Floor).Count() + mapInfo.GetAllPointsInRoomOfTerrain(v, RoomTemplateTerrain.Wall).Count());

            LogFile.Log.LogEntryDebug("Floor area for level: " + level + ": " + floorAreaForLevel, LogDebugLevel.Medium);

            //0.05 is a bit high
            double areaScaling      = 0.03;
            var    monstersForLevel = (int)Math.Floor(floorAreaForLevel * areaScaling);

            var monsterSetsForLevel = monsterSets.Where(s => s.difficulty == levelDifficulty);

            if (!monsterSetsForLevel.Any())
            {
                monsterSetsForLevel = monsterSets.Where(s => s.difficulty <= levelDifficulty);
            }

            var newSets    = monsterSetsForLevel.Except(monsterSetsUsed);
            var setsToPick = newSets;

            if (!newSets.Any())
            {
                setsToPick = monsterSetsForLevel;
            }

            var setToUse = setsToPick.RandomElement();

            LogFile.Log.LogEntryDebug("Use set of difficulty " + setToUse.difficulty + " for level " + Game.Dungeon.DungeonInfo.LevelNaming[level], LogDebugLevel.Medium);

            monsterSetsUsed.Add(setToUse);

            AddMonstersToLevelGaussianDistribution(mapInfo, level, setToUse.monsterSet, monstersForLevel);

            //Not working for the time being - maybe check tomorrow morning

            /*
             * //var heurestics = new MapHeuristics(mapInfo.Model.GraphNoCycles, 0);
             *
             * for (int i = 0; i < 10; i++)
             * {
             *  AddMonsterLinearPatrol(mapInfo, new RogueBasin.Creatures.PatrolBot(), terminalBranchNodes, level);
             * }*/
        }
예제 #3
0
 public void CorridorsCanBeFilteredOut()
 {
     var mapInfo = new MapInfo(GetStandardMapInfoBuilderForTemplates());
     var filteredRooms = mapInfo.FilterOutCorridors(new List<int> { 0, 1, 2 }).ToList();
     CollectionAssert.AreEqual(new List<int>{2}, filteredRooms);
 }
예제 #4
0
        public void CreateMonstersForLevels(MapInfo mapInfo, IEnumerable <int> levelsToProcess, Dictionary <int, int> levelDifficulty)
        {
            SetupMonsterWeightings();

            var monsterSetsUsed = new List <MonsterSet>();

            foreach (var level in levelsToProcess)
            {
                var roomVertices      = mapInfo.FilterOutCorridors(mapInfo.GetRoomIndicesForLevel(level));
                var floorAreaForLevel = roomVertices.Sum(v => mapInfo.GetAllPointsInRoomOfTerrain(v, RoomTemplateTerrain.Floor).Count() + mapInfo.GetAllPointsInRoomOfTerrain(v, RoomTemplateTerrain.Wall).Count());
                LogFile.Log.LogEntryDebug("Floor area for level: " + level + ": " + floorAreaForLevel, LogDebugLevel.Medium);

                //0.05 is a bit high
                double areaScaling      = 0.03;
                var    monstersForLevel = (int)Math.Floor(floorAreaForLevel * areaScaling);

                var monsterSetsForLevel = monsterSets.Where(s => s.difficulty == levelDifficulty[level]);

                if (!monsterSetsForLevel.Any())
                {
                    monsterSetsForLevel = monsterSets.Where(s => s.difficulty <= levelDifficulty[level]);
                }

                var newSets    = monsterSetsForLevel.Except(monsterSetsUsed);
                var setsToPick = newSets;
                if (!newSets.Any())
                {
                    setsToPick = monsterSetsForLevel;
                }

                var setToUse = setsToPick.RandomElement();

                monstersForLevel = (int)Math.Ceiling(monstersForLevel * setToUse.scaling);

                if (Game.Dungeon.Difficulty == GameDifficulty.Easy)
                {
                    monstersForLevel = (int)Math.Ceiling(monstersForLevel * 0.5);
                }
                else if (Game.Dungeon.Difficulty == GameDifficulty.Medium)
                {
                    monstersForLevel = (int)Math.Ceiling(monstersForLevel * 1.0);
                }
                else if (Game.Dungeon.Difficulty == GameDifficulty.Hard)
                {
                    monstersForLevel = (int)Math.Ceiling(monstersForLevel * 1.2);
                }

                LogFile.Log.LogEntryDebug("Use set of difficulty " + setToUse.difficulty + " for level " + Game.Dungeon.DungeonInfo.LevelNaming[level], LogDebugLevel.Medium);

                monsterSetsUsed.Add(setToUse);

                Game.Dungeon.MonsterPlacement.AddMonstersToLevelGaussianDistribution(mapInfo, level, setToUse.monsterSet, monstersForLevel);

                var monsterSetContainsBarrels = setToUse.monsterSet.Where(t => t.Item2.GetType() == typeof(RogueBasin.Creatures.ExplosiveBarrel));

                if (monsterSetContainsBarrels.Any())
                {
                    AddMonstersToLevelGaussianDistribution(mapInfo, level, new List <Tuple <int, Monster> > {
                        new Tuple <int, Monster>(1, new RogueBasin.Creatures.ExplosiveBarrel())
                    }, monstersForLevel / 3);
                }

                //Not working for the time being - maybe check tomorrow morning

                /*
                 * //var heurestics = new MapHeuristics(mapInfo.Model.GraphNoCycles, 0);
                 *
                 * for (int i = 0; i < 10; i++)
                 * {
                 *  AddMonsterLinearPatrol(mapInfo, new RogueBasin.Creatures.PatrolBot(), terminalBranchNodes, level);
                 * }*/
            }
        }
예제 #5
0
        private void AddMonstersToRoomsOnLevelGaussianDistribution(MapInfo mapInfo, int level, IEnumerable <Monster> monster)
        {
            //Get the number of rooms
            var allRoomsAndCorridors = mapInfo.GetRoomIndicesForLevel(level).Except(new List <int> {
                mapInfo.StartRoom
            });
            var rooms = mapInfo.FilterOutCorridors(allRoomsAndCorridors).ToList();
            var candidatePointsInRooms = rooms.Select(room => mapInfo.GetAllPointsInRoomOfTerrain(room, RoomTemplateTerrain.Floor));
            var roomsAndPointsInRooms  = rooms.Zip(candidatePointsInRooms, Tuple.Create);

            var monstersToPlaceRandomized = monster.Shuffle().ToList();

            int noMonsters = monstersToPlaceRandomized.Count;
            int noRooms    = rooms.Count();

            LogFile.Log.LogEntryDebug("No rooms: " + noRooms + " Total monsters to place (level: " + level + "): " + noMonsters, LogDebugLevel.Medium);

            //Distribution amongst rooms, mostly evenly, scaled by room size

            var roomMonsterRatio = roomsAndPointsInRooms.Select(rp => Math.Max(0, Gaussian.BoxMuller(5, 3)) * rp.Item2.Count());

            double totalMonsterRatio = roomMonsterRatio.Sum();

            double ratioToTotalMonsterBudget = noMonsters / totalMonsterRatio;

            int[]  monstersPerRoom = new int[noRooms];
            double remainder       = 0.0;

            for (int i = 0; i < noRooms; i++)
            {
                double monsterBudget = roomMonsterRatio.ElementAt(i) * ratioToTotalMonsterBudget + remainder;

                double actualMonstersToPlace = Math.Floor(monsterBudget);

                double levelBudgetSpent    = actualMonstersToPlace;
                double levelBudgetLeftOver = monsterBudget - levelBudgetSpent;

                monstersPerRoom[i] = (int)actualMonstersToPlace;
                remainder          = levelBudgetLeftOver;

                //Any left over monster ratio gets added to the next level up
            }

            //Calculate actual number of monster levels placed

            int totalMonsters = monstersPerRoom.Sum();

            LogFile.Log.LogEntryDebug("Total monsters actually placed (level: " + level + "): " + noMonsters, LogDebugLevel.Medium);

            //Place monsters in rooms

            Dungeon dungeon = Game.Dungeon;

            int monsterPos = 0;

            for (int r = 0; r < noRooms; r++)
            {
                int monstersToPlaceInRoom = monstersPerRoom[r];

                var candidatePointsInRoom = roomsAndPointsInRooms.ElementAt(r).Item2.Shuffle();
                int monstersPlacedInRoom  = 0;

                foreach (var p in candidatePointsInRoom)
                {
                    if (monsterPos >= monstersToPlaceRandomized.Count)
                    {
                        LogFile.Log.LogEntryDebug("Trying to place too many monsters", LogDebugLevel.High);
                        monsterPos++;
                        break;
                    }

                    Monster mon = monstersToPlaceRandomized[monsterPos];
                    GiveMonsterStandardItems(mon);

                    bool placedSuccessfully = Game.Dungeon.AddMonster(mon, level, p);
                    if (placedSuccessfully)
                    {
                        monsterPos++;
                        monstersPlacedInRoom++;
                    }

                    if (monstersPlacedInRoom >= monstersToPlaceInRoom)
                    {
                        break;
                    }
                }
            }
        }