public static void FindAvailableAreas(string areaPrefix)
        {
            areaPrefix = areaPrefix.ToLower();

            // I guess we already cached this one. Do nothing else.
            if (AvailableAreas.ContainsKey(areaPrefix))
            {
                return;
            }

            AvailableAreas.Add(areaPrefix, new List <RandomDungeonArea>());

            foreach (KeyValuePair <uint, ActiveArea> area in ALFA.Shared.Modules.InfoStore.ActiveAreas)
            {
                if (area.Value.Tag.Contains(areaPrefix))
                {
                    RandomDungeonArea genericArea = new RandomDungeonArea();
                    string            north       = area.Value.Tag.Substring(area.Value.Tag.Length - 6, 1);
                    string            east        = area.Value.Tag.Substring(area.Value.Tag.Length - 5, 1);
                    string            south       = area.Value.Tag.Substring(area.Value.Tag.Length - 4, 1);
                    string            west        = area.Value.Tag.Substring(area.Value.Tag.Length - 3, 1);
                    string            up          = area.Value.Tag.Substring(area.Value.Tag.Length - 2, 1);
                    string            down        = area.Value.Tag.Substring(area.Value.Tag.Length - 1, 1);

                    int n, e, s, w, u, d;
                    if (Int32.TryParse(north, out n) && n == 1)
                    {
                        genericArea.AreaExits.Add(ExitDirection.North);
                    }
                    if (Int32.TryParse(east, out e) && e == 1)
                    {
                        genericArea.AreaExits.Add(ExitDirection.East);
                    }
                    if (Int32.TryParse(south, out s) && s == 1)
                    {
                        genericArea.AreaExits.Add(ExitDirection.South);
                    }
                    if (Int32.TryParse(west, out w) && w == 1)
                    {
                        genericArea.AreaExits.Add(ExitDirection.West);
                    }
                    if (Int32.TryParse(up, out u) && u == 1)
                    {
                        genericArea.AreaExits.Add(ExitDirection.Up);
                    }
                    if (Int32.TryParse(down, out d) && d == 1)
                    {
                        genericArea.AreaExits.Add(ExitDirection.Down);
                    }

                    genericArea.AreaId = area.Key;
                    AvailableAreas[areaPrefix].Add(genericArea);
                }
            }
        }
        public RandomDungeonArea GetEndArea()
        {
            int grabbedCR         = -1;
            RandomDungeonArea ret = null;

            foreach (RandomDungeonArea area in AreasOfDungeon)
            {
                if (area.CR > grabbedCR)
                {
                    ret       = area;
                    grabbedCR = area.CR;
                }
            }
            return(ret);
        }
        public RandomDungeonArea GetCurrentArea(CLRScriptBase script)
        {
            uint currentArea = script.GetArea(script.OBJECT_SELF);
            RandomDungeonArea currentAreaObject = null;

            foreach (RandomDungeonArea area in AreasOfDungeon)
            {
                if (area.AreaId == currentArea)
                {
                    currentAreaObject = area;
                    break;
                }
            }
            return(currentAreaObject);
        }
        public RandomDungeonArea GetAdjacentArea(CLRScriptBase script, ExitDirection exit, RandomDungeonArea CurrentArea)
        {
            int X = CurrentArea.X;
            int Y = CurrentArea.Y;
            int Z = CurrentArea.Z;

            switch (exit)
            {
            case ExitDirection.North:
                Y++;
                break;

            case ExitDirection.East:
                X++;
                break;

            case ExitDirection.South:
                Y--;
                break;

            case ExitDirection.West:
                X--;
                break;

            case ExitDirection.Up:
                Z++;
                break;

            case ExitDirection.Down:
                Z--;
                break;
            }

            RandomDungeonArea targetArea = null;

            foreach (RandomDungeonArea area in AreasOfDungeon)
            {
                if (area.X == X && area.Y == Y && area.Z == Z)
                {
                    targetArea = area;
                    break;
                }
            }
            return(targetArea);
        }
        public void CorrectDungeonCR()
        {
            RandomDungeonArea        start          = GetEntranceArea();
            List <RandomDungeonArea> remainingAreas = new List <RandomDungeonArea>();

            remainingAreas.AddRange(AreasOfDungeon);
            remainingAreas.Remove(start);
            start.CR = 0;
            List <RandomDungeonArea> nextAreas = new List <RandomDungeonArea>();
            List <RandomDungeonArea> lastAreas = new List <RandomDungeonArea>();

            lastAreas.Add(start);
            int CRtoSet = 1;

            while (remainingAreas.Count > 0)
            {
                foreach (RandomDungeonArea lastArea in lastAreas)
                {
                    foreach (RandomDungeonArea nextArea in lastArea.AdjacentAreas.Values)
                    {
                        if (remainingAreas.Contains(nextArea))
                        {
                            nextArea.CR = CRtoSet;
                            nextAreas.Add(nextArea);
                            remainingAreas.Remove(nextArea);
                        }
                    }
                }
                if (nextAreas.Count == 0)
                {
                    break;
                }
                lastAreas.Clear();
                lastAreas.AddRange(nextAreas);
                nextAreas.Clear();
                CRtoSet++;
            }
            int diff = 1 + CR - CRtoSet; // CRtoSet will always be 1 higher than the last area in the dungeon, because CRtoSet will increment on its way out.

            foreach (RandomDungeonArea area in AreasOfDungeon)
            {
                area.CR += diff;
            }
        }
        private void _setAreaCoordinates(RandomDungeonArea toExpand, RandomDungeonArea toAdd, ExitDirection exit)
        {
            switch (exit)
            {
            case ExitDirection.North:
                toAdd.X = toExpand.X;
                toAdd.Y = toExpand.Y + 1;
                toAdd.Z = toExpand.Z;
                break;

            case ExitDirection.East:
                toAdd.X = toExpand.X + 1;
                toAdd.Y = toExpand.Y;
                toAdd.Z = toExpand.Z;
                break;

            case ExitDirection.South:
                toAdd.X = toExpand.X;
                toAdd.Y = toExpand.Y - 1;
                toAdd.Z = toExpand.Z;
                break;

            case ExitDirection.West:
                toAdd.X = toExpand.X - 1;
                toAdd.Y = toExpand.Y;
                toAdd.Z = toExpand.Z;
                break;

            case ExitDirection.Up:
                toAdd.X = toExpand.X;
                toAdd.Y = toExpand.Y;
                toAdd.Z = toExpand.Z + 1;
                break;

            case ExitDirection.Down:
                toAdd.X = toExpand.X;
                toAdd.Y = toExpand.Y;
                toAdd.Z = toExpand.Z - 1;
                break;
            }
        }
Пример #7
0
        public Int32 ScriptMain([In] object[] ScriptParameters, [In] Int32 DefaultReturnCode)
        {
            int         command  = (int)ScriptParameters[0]; // ScriptParameterTypes[0] is typeof(int)
            string      name     = (string)ScriptParameters[1];
            int         state    = (int)ScriptParameters[2];
            string      template = (string)ScriptParameters[3];
            Infestation infest   = null;

            switch ((Command)command)
            {
            case Command.InitializeInfestations:
                if (!QuestStore.InfestationGrowthCounterStarted)
                {
                    Infestation.InitializeInfestations(this);
                    DelayCommand(HoursToSeconds(24), delegate { QuestStore.GrowAllInfestations(this); });
                }
                break;

            case Command.CreateInfestation:
                new Infestation(name, template, state, this);
                break;

            case Command.GrowInfestation:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    infest.GrowInfestation(this);
                }
                else
                {
                    SendMessageToAllDMs(NoInfest);
                }
                break;

            case Command.AddSpawnToInfestation:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    infest.AddSpawn(state, template);
                }
                else
                {
                    SendMessageToAllDMs(NoInfest);
                }
                break;

            case Command.RemoveSpawnFromInfestation:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    if (!infest.RemoveSpawn(state, template))
                    {
                        SendMessageToAllDMs(NoSpawn);
                    }
                }
                else
                {
                    SendMessageToAllDMs(NoInfest);
                }
                break;

            case Command.SetInfestationFecundity:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    infest.Fecundity = state;
                    infest.Save();
                }
                else
                {
                    SendMessageToAllDMs(NoInfest);
                }
                break;

            case Command.SpawnCreatureFromInfestation:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    infest.SpawnOneAtTier(this);
                }
                break;

            case Command.DegradeAreaInfestation:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    uint   degradedInfestationArea = GetArea(OBJECT_SELF);
                    string degradedInfestationTag  = GetTag(degradedInfestationArea);

                    if (infest.InfestedAreaLevels.ContainsKey(degradedInfestationTag))
                    {
                        if (infest.InfestedAreaLevels[degradedInfestationTag] <= 1)
                        {
                            infest.ClearArea(degradedInfestationTag, ALFA.Shared.Modules.InfoStore.ActiveAreas[degradedInfestationArea], this);
                            infest.Save();
                        }
                        else
                        {
                            infest.ChangeAreaLevel(degradedInfestationTag, ALFA.Shared.Modules.InfoStore.ActiveAreas[degradedInfestationArea], infest.InfestedAreaLevels[degradedInfestationTag] - 1, this);
                            infest.Save();
                        }
                    }
                }
                break;

            case Command.AddBossMonsterToInfestation:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    infest.AddBoss(template);
                }
                break;

            case Command.RemoveBossMonsterFromInfestation:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    infest.RemoveBoss(template);
                }
                break;

            case Command.PopulateInfestationGUIScreen:
                string infestName = GetLocalString(GetArea(OBJECT_SELF), Infestation.InfestNameVar);
                infest = QuestStore.GetInfestation(infestName);
                if (infest != null)
                {
                    infest.PopulateGUI(OBJECT_SELF, this);
                }
                break;

            case Command.UpgradeInfestationCreatureTier:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    if (!infest.Spawns.ContainsKey(state))
                    {
                        SendMessageToAllDMs("No spawns found at that tier.");
                    }
                    else if (infest.Spawns[state].Count <= 1)
                    {
                        SendMessageToAllDMs("Cannot upgrade tier for " + template + " as there are too few creatures at that tier.");
                    }
                    else if (!infest.Spawns[state].Contains(template))
                    {
                        SendMessageToAllDMs(template + " does not exist at that tier.");
                    }
                    else
                    {
                        infest.AddSpawn(state + 1, template);
                        infest.RemoveSpawn(state, template);
                    }
                }
                break;

            case Command.DowngradeInfestationCreatureTier:
                infest = QuestStore.GetInfestation(name);
                if (infest != null)
                {
                    if (state <= 1)
                    {
                        SendMessageToAllDMs("Creature is already at the minimum tier.");
                    }
                    else if (!infest.Spawns.ContainsKey(state))
                    {
                        SendMessageToAllDMs("No spawns found at that tier.");
                    }
                    else if (infest.Spawns[state].Count <= 1 &&
                             infest.Spawns.ContainsKey(state + 1) &&
                             infest.Spawns[state + 1].Count > 0)
                    {
                        SendMessageToAllDMs("Cannot downgrade tier for " + template + " as there are creatures at the next tier.");
                    }
                    else if (!infest.Spawns[state].Contains(template))
                    {
                        SendMessageToAllDMs(template + " does not exist at that tier.");
                    }
                    else
                    {
                        infest.AddSpawn(state - 1, template);
                        infest.RemoveSpawn(state, template);
                    }
                }
                break;

            case Command.PrintInfestations:
                foreach (Infestation inf in QuestStore.LoadedInfestations)
                {
                    SendMessageToAllDMs(inf.ToString());
                }
                break;

            case Command.InstanceDungeon:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    return(0);
                }
                DungeonStore.FindAvailableAreas(template);
                RandomDungeon dung = new RandomDungeon(template, state, state, name, this);
                dung.retLoc = GetLocation(OBJECT_SELF);
                dung.CorrectDungeonCR();
                DungeonStore.Dungeons.Add(name, dung);
                break;

            case Command.EnterDungeon:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    RandomDungeon     dungeon = DungeonStore.Dungeons[name];
                    RandomDungeonArea enter   = dungeon.GetEntranceArea();
                    enter.LoadArea(this);
                    enter.TransitionToArea(this, enter.DungeonExit);
                }
                break;

            case Command.DungeonTransitionNorth:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    RandomDungeon     dungeon = DungeonStore.Dungeons[name];
                    RandomDungeonArea current = dungeon.GetCurrentArea(this);
                    if (current == null)
                    {
                        return(0);
                    }
                    if (current.DungeonExit == ExitDirection.North)
                    {
                        JumpToLocation(dungeon.retLoc);
                        return(0);
                    }
                    RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.North, current);
                    if (target == null)
                    {
                        SendMessageToPC(OBJECT_SELF, "This appears to be a dead end.");
                        return(0);
                    }
                    if (!target.LoadArea(this))
                    {
                        SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end.");
                        return(0);
                    }
                    target.TransitionToArea(this, ExitDirection.South);
                }
                break;

            case Command.DungeonTransitionEast:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    RandomDungeon     dungeon = DungeonStore.Dungeons[name];
                    RandomDungeonArea current = dungeon.GetCurrentArea(this);
                    if (current == null)
                    {
                        return(0);
                    }
                    if (current.DungeonExit == ExitDirection.East)
                    {
                        JumpToLocation(dungeon.retLoc);
                        return(0);
                    }
                    RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.East, current);
                    if (target == null)
                    {
                        SendMessageToPC(OBJECT_SELF, "This appears to be a dead end.");
                        return(0);
                    }
                    if (!target.LoadArea(this))
                    {
                        SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end.");
                        return(0);
                    }
                    target.TransitionToArea(this, ExitDirection.West);
                }
                break;

            case Command.DungeonTransitionSouth:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    RandomDungeon     dungeon = DungeonStore.Dungeons[name];
                    RandomDungeonArea current = dungeon.GetCurrentArea(this);
                    if (current == null)
                    {
                        return(0);
                    }
                    if (current.DungeonExit == ExitDirection.South)
                    {
                        JumpToLocation(dungeon.retLoc);
                        return(0);
                    }
                    RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.South, current);
                    if (target == null)
                    {
                        SendMessageToPC(OBJECT_SELF, "This appears to be a dead end.");
                        return(0);
                    }
                    if (!target.LoadArea(this))
                    {
                        SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end.");
                        return(0);
                    }
                    target.TransitionToArea(this, ExitDirection.North);
                }
                break;

            case Command.DungeonTransitionWest:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    RandomDungeon     dungeon = DungeonStore.Dungeons[name];
                    RandomDungeonArea current = dungeon.GetCurrentArea(this);
                    if (current == null)
                    {
                        return(0);
                    }
                    if (current.DungeonExit == ExitDirection.West)
                    {
                        JumpToLocation(dungeon.retLoc);
                        return(0);
                    }
                    RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.West, current);
                    if (target == null)
                    {
                        SendMessageToPC(OBJECT_SELF, "This appears to be a dead end.");
                        return(0);
                    }
                    if (!target.LoadArea(this))
                    {
                        SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end.");
                        return(0);
                    }
                    target.TransitionToArea(this, ExitDirection.East);
                }
                break;

            case Command.DungeonTransitionUp:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    RandomDungeon     dungeon = DungeonStore.Dungeons[name];
                    RandomDungeonArea current = dungeon.GetCurrentArea(this);
                    if (current == null)
                    {
                        return(0);
                    }
                    if (current.DungeonExit == ExitDirection.Up)
                    {
                        JumpToLocation(dungeon.retLoc);
                        return(0);
                    }
                    RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.Up, current);
                    if (target == null)
                    {
                        SendMessageToPC(OBJECT_SELF, "This appears to be a dead end.");
                        return(0);
                    }
                    if (!target.LoadArea(this))
                    {
                        SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end.");
                        return(0);
                    }
                    target.TransitionToArea(this, ExitDirection.Down);
                }
                break;

            case Command.DungeonTransitionDown:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    RandomDungeon     dungeon = DungeonStore.Dungeons[name];
                    RandomDungeonArea current = dungeon.GetCurrentArea(this);
                    if (current == null)
                    {
                        return(0);
                    }
                    if (current.DungeonExit == ExitDirection.Down)
                    {
                        JumpToLocation(dungeon.retLoc);
                        return(0);
                    }
                    RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.Down, current);
                    if (target == null)
                    {
                        SendMessageToPC(OBJECT_SELF, "This appears to be a dead end.");
                        return(0);
                    }
                    if (!target.LoadArea(this))
                    {
                        SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end.");
                        return(0);
                    }
                    target.TransitionToArea(this, ExitDirection.Up);
                }
                break;

            case Command.AddDungeonSpawn:
                if (!DungeonStore.DungeonSpawns.ContainsKey(name))
                {
                    DungeonStore.DungeonSpawns.Add(name, new Dictionary <int, List <string> >());
                }
                if (!DungeonStore.DungeonSpawns[name].ContainsKey(state))
                {
                    DungeonStore.DungeonSpawns[name].Add(state, new List <string>());
                }
                DungeonStore.DungeonSpawns[name][state].Add(template);
                break;

            case Command.RemoveDungeonSpawn:
                if (DungeonStore.DungeonSpawns.ContainsKey(name) &&
                    DungeonStore.DungeonSpawns[name].ContainsKey(state) &&
                    DungeonStore.DungeonSpawns[name][state].Contains(template))
                {
                    DungeonStore.DungeonSpawns[name][state].Remove(template);
                }
                break;

            case Command.SetDungeonSpawnType:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    foreach (RandomDungeonArea area in DungeonStore.Dungeons[name].AreasOfDungeon)
                    {
                        area.SpawnType = template;
                    }
                }
                break;

            case Command.DisposeDungeon:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    RandomDungeon toDispose = DungeonStore.Dungeons[name];
                    toDispose.DisposeDungeon(this);
                    DungeonStore.Dungeons.Remove(name);
                }
                break;

            case Command.AddDungeonTrap:
                if (!DungeonStore.DungeonTraps.ContainsKey(name))
                {
                    DungeonStore.DungeonTraps.Add(name, new Dictionary <int, List <string> >());
                }
                if (!DungeonStore.DungeonTraps[name].ContainsKey(state))
                {
                    DungeonStore.DungeonTraps[name].Add(state, new List <string>());
                }
                DungeonStore.DungeonTraps[name][state].Add(template);
                break;

            case Command.RemoveDungeonTrap:
                if (DungeonStore.DungeonTraps.ContainsKey(name) &&
                    DungeonStore.DungeonTraps[name].ContainsKey(state) &&
                    DungeonStore.DungeonTraps[name][state].Contains(template))
                {
                    DungeonStore.DungeonTraps[name][state].Remove(template);
                }
                break;

            case Command.SetDungeonTrapType:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    foreach (RandomDungeonArea area in DungeonStore.Dungeons[name].AreasOfDungeon)
                    {
                        area.TrapType = template;
                    }
                }
                break;

            case Command.SetDungeonQuestObjective:
                if (DungeonStore.Dungeons.ContainsKey(name))
                {
                    DungeonStore.Dungeons[name].GetEndArea().Quest = template;
                }
                break;

            case Command.PrintDungeons:
                foreach (KeyValuePair <string, RandomDungeon> dungeon in DungeonStore.Dungeons)
                {
                    SendMessageToAllDMs(dungeon.Key);
                    foreach (RandomDungeonArea area in dungeon.Value.AreasOfDungeon)
                    {
                        SendMessageToAllDMs(GetName(area.TemplateAreaId) + "(" + area.TemplateAreaId + ") : " + GetName(area.AreaId) + "(" + area.AreaId + ") CR " + area.CR + "(" + area.X + "," + area.Y + "," + area.Z + ")");
                    }
                }
                break;
            }
            return(0);
        }
        public RandomDungeon(string areaPrefix, int areasToGenerate, int cr, string name, CLRScriptBase script)
        {
            CR = cr;
            DungeonStore.FindAvailableAreas(areaPrefix);

            List <RandomDungeonArea> sourceAreas = new List <RandomDungeonArea>();

            if (areasToGenerate > 1)
            {
                foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix])
                {
                    if (area.AreaExits.Count <= areasToGenerate && area.AreaExits.Count > 1)
                    {
                        sourceAreas.Add(area);
                    }
                }
            }
            else
            {
                foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix])
                {
                    if (area.AreaExits.Count == 1)
                    {
                        sourceAreas.Add(area);
                    }
                }
            }

            RandomDungeonArea template = sourceAreas[rnd.Next(sourceAreas.Count)];
            RandomDungeonArea toAdd    = new RandomDungeonArea();

            toAdd.TemplateAreaId = template.AreaId;
            toAdd.DungeonName    = name;
            toAdd.AreaExits      = new List <ExitDirection>();
            toAdd.AreaExits.AddRange(template.AreaExits);
            toAdd.DungeonExit = toAdd.AreaExits[rnd.Next(toAdd.AreaExits.Count)];
            toAdd.AreaExits.Remove(toAdd.DungeonExit);
            toAdd.X          = areasToGenerate + 1;
            toAdd.Y          = areasToGenerate + 1;
            toAdd.Z          = areasToGenerate + 1;
            toAdd.CR         = cr;
            areasToGenerate -= toAdd.AreaExits.Count;
            areasToGenerate -= 1;
            AreasOfDungeon.Add(toAdd);

            List <RandomDungeonArea> areasNeedingAdjacentAreas = new List <RandomDungeonArea>();

            areasNeedingAdjacentAreas.Add(toAdd);

            while (areasNeedingAdjacentAreas.Count > 0)
            {
                // Randomly select one of our bare ends to build out from.
                RandomDungeonArea toExpand = areasNeedingAdjacentAreas[rnd.Next(areasNeedingAdjacentAreas.Count)];

                // Build a temporary collection of exit directions from this area, but
                // don't count the directions that already have adjacent areas.
                List <ExitDirection> NextAreaDirections = new List <ExitDirection>();
                NextAreaDirections.AddRange(toExpand.AreaExits);
                foreach (ExitDirection used in toExpand.AdjacentAreas.Keys)
                {
                    NextAreaDirections.Remove(used);
                }
                if (NextAreaDirections.Count == 0)
                {
                    // If that's all of the exits, then this area shouldn't actually be on the list
                    // of candidates to expand.
                    areasNeedingAdjacentAreas.Remove(toExpand);
                    continue;
                }

                // Pick a random direction out of those available and set the new area's coordinates
                // appropriately.
                ExitDirection nextAreaDirection = NextAreaDirections[rnd.Next(NextAreaDirections.Count)];
                toAdd = new RandomDungeonArea();
                _setAreaCoordinates(toExpand, toAdd, nextAreaDirection);

                // Scan for adjacent areas, and determine the necessary parts of the target area.
                Dictionary <ExitDirection, bool> necessaryBorders          = new Dictionary <ExitDirection, bool>();
                Dictionary <ExitDirection, RandomDungeonArea> adjacentToBe = new Dictionary <ExitDirection, RandomDungeonArea>();
                _buildBorders(necessaryBorders, adjacentToBe, toAdd);


                // If we can't generate more areas, order the new areas to not open up any more exits that we'd have to
                // attach areas to. Future additions will just be attaching things to dangling ATs.
                if (areasToGenerate <= 0)
                {
                    _sealBorders(necessaryBorders);
                }

                // Now that we know where the area is and what borders it has to maintain, we
                // loop through the areas that are available and build a list of all of the ones
                // that fit the restrictions of the area's location.
                sourceAreas.Clear();
                foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix])
                {
                    bool areaUseful = true;
                    foreach (KeyValuePair <ExitDirection, bool> dir in necessaryBorders)
                    {
                        if (dir.Value)
                        {
                            if (!area.AreaExits.Contains(dir.Key))
                            {
                                areaUseful = false;
                            }
                        }
                        if (!dir.Value)
                        {
                            if (area.AreaExits.Contains(dir.Key))
                            {
                                areaUseful = false;
                            }
                        }
                        if (!areaUseful)
                        {
                            break;
                        }
                    }
                    if (areaUseful)
                    {
                        sourceAreas.Add(area);
                    }
                }

                if (sourceAreas.Count >= 1)
                {
                    // If we have more at least one area that fits the bill, we'll try to use that, so that
                    // the dungeon feels as connected and continuous as possible.
                    template             = sourceAreas[rnd.Next(sourceAreas.Count)];
                    toAdd.TemplateAreaId = template.AreaId;
                    toAdd.DungeonName    = name;
                    toAdd.AreaExits.AddRange(template.AreaExits);
                    toAdd.CR = cr;
                    foreach (KeyValuePair <ExitDirection, RandomDungeonArea> adj in adjacentToBe)
                    {
                        toAdd.AdjacentAreas.Add(adj.Key, adj.Value);
                        switch (adj.Key)
                        {
                        case ExitDirection.North:
                            adj.Value.AdjacentAreas.Add(ExitDirection.South, toAdd);
                            break;

                        case ExitDirection.South:
                            adj.Value.AdjacentAreas.Add(ExitDirection.North, toAdd);
                            break;

                        case ExitDirection.East:
                            adj.Value.AdjacentAreas.Add(ExitDirection.West, toAdd);
                            break;

                        case ExitDirection.West:
                            adj.Value.AdjacentAreas.Add(ExitDirection.East, toAdd);
                            break;

                        case ExitDirection.Up:
                            adj.Value.AdjacentAreas.Add(ExitDirection.Down, toAdd);
                            break;

                        case ExitDirection.Down:
                            adj.Value.AdjacentAreas.Add(ExitDirection.Up, toAdd);
                            break;
                        }
                    }
                    areasToGenerate -= (toAdd.AreaExits.Count - toAdd.AdjacentAreas.Count);
                    AreasOfDungeon.Add(toAdd);
                    areasNeedingAdjacentAreas.Add(toAdd);
                }
                else
                {
                    // But if no area fits the bill, we loop over each of the exits we're expecting and
                    // attach the dead end area with the appropriate exit to them.
                    foreach (KeyValuePair <ExitDirection, RandomDungeonArea> adj in adjacentToBe)
                    {
                        int X = toAdd.X;
                        int Y = toAdd.Y;
                        int Z = toAdd.Z;
                        switch (adj.Key)
                        {
                        case ExitDirection.North:
                            template = getSingleExitArea(ExitDirection.South, areaPrefix);
                            break;

                        case ExitDirection.South:
                            template = getSingleExitArea(ExitDirection.North, areaPrefix);
                            break;

                        case ExitDirection.East:
                            template = getSingleExitArea(ExitDirection.West, areaPrefix);
                            break;

                        case ExitDirection.West:
                            template = getSingleExitArea(ExitDirection.East, areaPrefix);
                            break;

                        case ExitDirection.Up:
                            template = getSingleExitArea(ExitDirection.Down, areaPrefix);
                            break;

                        case ExitDirection.Down:
                            template = getSingleExitArea(ExitDirection.Up, areaPrefix);
                            break;
                        }
                        toAdd   = new RandomDungeonArea();
                        toAdd.X = X;
                        toAdd.Y = Y;
                        toAdd.Z = Z;
                        toAdd.TemplateAreaId = template.AreaId;
                        toAdd.DungeonName    = name;
                        toAdd.AreaExits.AddRange(template.AreaExits);
                        toAdd.AdjacentAreas.Add(adj.Key, adj.Value);
                        switch (adj.Key)
                        {
                        case ExitDirection.North:
                            adj.Value.AdjacentAreas.Add(ExitDirection.South, toAdd);
                            break;

                        case ExitDirection.South:
                            adj.Value.AdjacentAreas.Add(ExitDirection.North, toAdd);
                            break;

                        case ExitDirection.East:
                            adj.Value.AdjacentAreas.Add(ExitDirection.West, toAdd);
                            break;

                        case ExitDirection.West:
                            adj.Value.AdjacentAreas.Add(ExitDirection.East, toAdd);
                            break;

                        case ExitDirection.Up:
                            adj.Value.AdjacentAreas.Add(ExitDirection.Down, toAdd);
                            break;

                        case ExitDirection.Down:
                            adj.Value.AdjacentAreas.Add(ExitDirection.Up, toAdd);
                            break;
                        }
                        areasToGenerate -= (toAdd.AreaExits.Count - toAdd.AdjacentAreas.Count);
                        AreasOfDungeon.Add(toAdd);
                        areasNeedingAdjacentAreas.Add(toAdd);
                    }
                }
            }
        }
 private void _buildBorders(Dictionary <ExitDirection, bool> necessaryBorders, Dictionary <ExitDirection, RandomDungeonArea> adjacentToBe, RandomDungeonArea toAdd)
 {
     foreach (RandomDungeonArea area in AreasOfDungeon)
     {
         if (area.X == toAdd.X && area.Y == toAdd.Y && area.Z == toAdd.Z + 1)
         {
             // Area is above the new area.
             if (area.AreaExits.Contains(ExitDirection.Down))
             {
                 necessaryBorders.Add(ExitDirection.Up, true);
                 adjacentToBe.Add(ExitDirection.Up, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.Up))
             {
                 // This location might have double end caps in it.
                 necessaryBorders.Add(ExitDirection.Up, false);
             }
         }
         else if (area.X == toAdd.X && area.Y == toAdd.Y && area.Z == toAdd.Z - 1)
         {
             if (area.AreaExits.Contains(ExitDirection.Up))
             {
                 necessaryBorders.Add(ExitDirection.Down, true);
                 adjacentToBe.Add(ExitDirection.Down, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.Down))
             {
                 necessaryBorders.Add(ExitDirection.Down, false);
             }
         }
         else if (area.X == toAdd.X + 1 && area.Y == toAdd.Y && area.Z == toAdd.Z)
         {
             if (area.AreaExits.Contains(ExitDirection.West))
             {
                 necessaryBorders.Add(ExitDirection.East, true);
                 adjacentToBe.Add(ExitDirection.East, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.East))
             {
                 necessaryBorders.Add(ExitDirection.East, false);
             }
         }
         else if (area.X == toAdd.X - 1 && area.Y == toAdd.Y && area.Z == toAdd.Z)
         {
             if (area.AreaExits.Contains(ExitDirection.East))
             {
                 necessaryBorders.Add(ExitDirection.West, true);
                 adjacentToBe.Add(ExitDirection.West, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.West))
             {
                 necessaryBorders.Add(ExitDirection.West, false);
             }
         }
         else if (area.X == toAdd.X && area.Y == toAdd.Y + 1 && area.Z == toAdd.Z)
         {
             if (area.AreaExits.Contains(ExitDirection.South))
             {
                 necessaryBorders.Add(ExitDirection.North, true);
                 adjacentToBe.Add(ExitDirection.North, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.North))
             {
                 necessaryBorders.Add(ExitDirection.North, false);
             }
         }
         else if (area.X == toAdd.X && area.Y == toAdd.Y - 1 && area.Z == toAdd.Z)
         {
             if (area.AreaExits.Contains(ExitDirection.North))
             {
                 necessaryBorders.Add(ExitDirection.South, true);
                 adjacentToBe.Add(ExitDirection.South, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.South))
             {
                 necessaryBorders.Add(ExitDirection.South, false);
             }
         }
     }
 }
        public static void FindAvailableAreas(string areaPrefix)
        {
            areaPrefix = areaPrefix.ToLower();

            // I guess we already cached this one. Do nothing else.
            if (AvailableAreas.ContainsKey(areaPrefix)) { return; }

            AvailableAreas.Add(areaPrefix, new List<RandomDungeonArea>());

            foreach (KeyValuePair<uint, ActiveArea> area in ALFA.Shared.Modules.InfoStore.ActiveAreas)
            {
                if(area.Value.Tag.Contains(areaPrefix))
                {
                    RandomDungeonArea genericArea = new RandomDungeonArea();
                    string north = area.Value.Tag.Substring(area.Value.Tag.Length - 6, 1);
                    string east = area.Value.Tag.Substring(area.Value.Tag.Length - 5, 1);
                    string south = area.Value.Tag.Substring(area.Value.Tag.Length - 4, 1);
                    string west = area.Value.Tag.Substring(area.Value.Tag.Length - 3, 1);
                    string up = area.Value.Tag.Substring(area.Value.Tag.Length - 2, 1);
                    string down = area.Value.Tag.Substring(area.Value.Tag.Length - 1, 1);

                    int n, e, s, w, u, d;
                    if (Int32.TryParse(north, out n) && n == 1) genericArea.AreaExits.Add(ExitDirection.North);
                    if (Int32.TryParse(east, out e) && e == 1) genericArea.AreaExits.Add(ExitDirection.East);
                    if (Int32.TryParse(south, out s) && s == 1) genericArea.AreaExits.Add(ExitDirection.South);
                    if (Int32.TryParse(west, out w) && w == 1) genericArea.AreaExits.Add(ExitDirection.West);
                    if (Int32.TryParse(up, out u) && u == 1) genericArea.AreaExits.Add(ExitDirection.Up);
                    if (Int32.TryParse(down, out d) && d == 1) genericArea.AreaExits.Add(ExitDirection.Down);

                    genericArea.AreaId = area.Key;
                    AvailableAreas[areaPrefix].Add(genericArea);
                }
            }
        }
        public RandomDungeonArea GetAdjacentArea(CLRScriptBase script, ExitDirection exit, RandomDungeonArea CurrentArea)
        {
            int X = CurrentArea.X;
            int Y = CurrentArea.Y;
            int Z = CurrentArea.Z;

            switch(exit)
            {
                case ExitDirection.North:
                    Y++;
                    break;
                case ExitDirection.East:
                    X++;
                    break;
                case ExitDirection.South:
                    Y--;
                    break;
                case ExitDirection.West:
                    X--;
                    break;
                case ExitDirection.Up:
                    Z++;
                    break;
                case ExitDirection.Down:
                    Z--;
                    break;
            }

            RandomDungeonArea targetArea = null;
            foreach(RandomDungeonArea area in AreasOfDungeon)
            {
                if(area.X == X && area.Y == Y && area.Z == Z)
                {
                    targetArea = area;
                    break;
                }
            }
            return targetArea;
        }
 private void _setAreaCoordinates(RandomDungeonArea toExpand, RandomDungeonArea toAdd, ExitDirection exit)
 {
     switch (exit)
     {
         case ExitDirection.North:
             toAdd.X = toExpand.X;
             toAdd.Y = toExpand.Y + 1;
             toAdd.Z = toExpand.Z;
             break;
         case ExitDirection.East:
             toAdd.X = toExpand.X + 1;
             toAdd.Y = toExpand.Y;
             toAdd.Z = toExpand.Z;
             break;
         case ExitDirection.South:
             toAdd.X = toExpand.X;
             toAdd.Y = toExpand.Y - 1;
             toAdd.Z = toExpand.Z;
             break;
         case ExitDirection.West:
             toAdd.X = toExpand.X - 1;
             toAdd.Y = toExpand.Y;
             toAdd.Z = toExpand.Z;
             break;
         case ExitDirection.Up:
             toAdd.X = toExpand.X;
             toAdd.Y = toExpand.Y;
             toAdd.Z = toExpand.Z + 1;
             break;
         case ExitDirection.Down:
             toAdd.X = toExpand.X;
             toAdd.Y = toExpand.Y;
             toAdd.Z = toExpand.Z - 1;
             break;
     }
 }
        public RandomDungeon(string areaPrefix, int areasToGenerate, int cr, string name, CLRScriptBase script)
        {
            CR = cr;
            DungeonStore.FindAvailableAreas(areaPrefix);

            List<RandomDungeonArea> sourceAreas = new List<RandomDungeonArea>();
            if (areasToGenerate > 1)
            {
                foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix])
                {
                    if (area.AreaExits.Count <= areasToGenerate && area.AreaExits.Count > 1)
                    {
                        sourceAreas.Add(area);
                    }
                }
            }
            else
            {
                foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix])
                {
                    if (area.AreaExits.Count == 1)
                    {
                        sourceAreas.Add(area);
                    }
                }
            }

            RandomDungeonArea template = sourceAreas[rnd.Next(sourceAreas.Count)];
            RandomDungeonArea toAdd = new RandomDungeonArea();
            toAdd.TemplateAreaId = template.AreaId;
            toAdd.DungeonName = name;
            toAdd.AreaExits = new List<ExitDirection>();
            toAdd.AreaExits.AddRange(template.AreaExits);
            toAdd.DungeonExit = toAdd.AreaExits[rnd.Next(toAdd.AreaExits.Count)];
            toAdd.AreaExits.Remove(toAdd.DungeonExit);
            toAdd.X = areasToGenerate + 1;
            toAdd.Y = areasToGenerate + 1;
            toAdd.Z = areasToGenerate + 1;
            toAdd.CR = cr;
            areasToGenerate -= toAdd.AreaExits.Count;
            areasToGenerate -= 1;
            AreasOfDungeon.Add(toAdd);

            List<RandomDungeonArea> areasNeedingAdjacentAreas = new List<RandomDungeonArea>();
            areasNeedingAdjacentAreas.Add(toAdd);

            while (areasNeedingAdjacentAreas.Count > 0)
            {
                // Randomly select one of our bare ends to build out from.
                RandomDungeonArea toExpand = areasNeedingAdjacentAreas[rnd.Next(areasNeedingAdjacentAreas.Count)];

                // Build a temporary collection of exit directions from this area, but
                // don't count the directions that already have adjacent areas.
                List<ExitDirection> NextAreaDirections = new List<ExitDirection>();
                NextAreaDirections.AddRange(toExpand.AreaExits);
                foreach(ExitDirection used in toExpand.AdjacentAreas.Keys)
                {
                    NextAreaDirections.Remove(used);
                }
                if(NextAreaDirections.Count == 0)
                {
                    // If that's all of the exits, then this area shouldn't actually be on the list
                    // of candidates to expand.
                    areasNeedingAdjacentAreas.Remove(toExpand);
                    continue;
                }

                // Pick a random direction out of those available and set the new area's coordinates
                // appropriately.
                ExitDirection nextAreaDirection = NextAreaDirections[rnd.Next(NextAreaDirections.Count)];
                toAdd = new RandomDungeonArea();
                _setAreaCoordinates(toExpand, toAdd, nextAreaDirection);

                // Scan for adjacent areas, and determine the necessary parts of the target area.
                Dictionary<ExitDirection, bool> necessaryBorders = new Dictionary<ExitDirection, bool>();
                Dictionary<ExitDirection, RandomDungeonArea> adjacentToBe = new Dictionary<ExitDirection, RandomDungeonArea>();
                _buildBorders(necessaryBorders, adjacentToBe, toAdd);


                // If we can't generate more areas, order the new areas to not open up any more exits that we'd have to
                // attach areas to. Future additions will just be attaching things to dangling ATs.
                if(areasToGenerate <= 0) _sealBorders(necessaryBorders);

                // Now that we know where the area is and what borders it has to maintain, we
                // loop through the areas that are available and build a list of all of the ones
                // that fit the restrictions of the area's location.
                sourceAreas.Clear();
                foreach(RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix])
                {
                    bool areaUseful = true;
                    foreach(KeyValuePair<ExitDirection, bool> dir in necessaryBorders)
                    {
                        if(dir.Value)
                        {
                            if(!area.AreaExits.Contains(dir.Key)) areaUseful = false;
                        }
                        if(!dir.Value)
                        {
                            if(area.AreaExits.Contains(dir.Key)) areaUseful = false;
                        }
                        if(!areaUseful) break;
                    }
                    if(areaUseful) sourceAreas.Add(area);
                }

                if(sourceAreas.Count >= 1)
                {
                    // If we have more at least one area that fits the bill, we'll try to use that, so that
                    // the dungeon feels as connected and continuous as possible.
                    template = sourceAreas[rnd.Next(sourceAreas.Count)];
                    toAdd.TemplateAreaId = template.AreaId;
                    toAdd.DungeonName = name;
                    toAdd.AreaExits.AddRange(template.AreaExits);
                    toAdd.CR = cr;
                    foreach(KeyValuePair<ExitDirection, RandomDungeonArea> adj in adjacentToBe)
                    {
                        toAdd.AdjacentAreas.Add(adj.Key, adj.Value);
                        switch(adj.Key)
                        {
                            case ExitDirection.North:
                                adj.Value.AdjacentAreas.Add(ExitDirection.South, toAdd);
                                break;
                            case ExitDirection.South:
                                adj.Value.AdjacentAreas.Add(ExitDirection.North, toAdd);
                                break;
                            case ExitDirection.East:
                                adj.Value.AdjacentAreas.Add(ExitDirection.West, toAdd);
                                break;
                            case ExitDirection.West:
                                adj.Value.AdjacentAreas.Add(ExitDirection.East, toAdd);
                                break;
                            case ExitDirection.Up:
                                adj.Value.AdjacentAreas.Add(ExitDirection.Down, toAdd);
                                break;
                            case ExitDirection.Down:
                                adj.Value.AdjacentAreas.Add(ExitDirection.Up, toAdd);
                                break;
                        }
                    }
                    areasToGenerate -= (toAdd.AreaExits.Count - toAdd.AdjacentAreas.Count);
                    AreasOfDungeon.Add(toAdd);
                    areasNeedingAdjacentAreas.Add(toAdd);
                }
                else
                {
                    // But if no area fits the bill, we loop over each of the exits we're expecting and
                    // attach the dead end area with the appropriate exit to them.
                    foreach(KeyValuePair<ExitDirection, RandomDungeonArea> adj in adjacentToBe)
                    {
                        int X = toAdd.X;
                        int Y = toAdd.Y;
                        int Z = toAdd.Z;
                        switch(adj.Key)
                        {
                            case ExitDirection.North:
                                template = getSingleExitArea(ExitDirection.South, areaPrefix);
                                break;
                            case ExitDirection.South:
                                template = getSingleExitArea(ExitDirection.North, areaPrefix);
                                break;
                            case ExitDirection.East:
                                template = getSingleExitArea(ExitDirection.West, areaPrefix);
                                break;
                            case ExitDirection.West:
                                template = getSingleExitArea(ExitDirection.East, areaPrefix);
                                break;
                            case ExitDirection.Up:
                                template = getSingleExitArea(ExitDirection.Down, areaPrefix);
                                break;
                            case ExitDirection.Down:
                                template = getSingleExitArea(ExitDirection.Up, areaPrefix);
                                break;
                        }
                        toAdd = new RandomDungeonArea();
                        toAdd.X = X;
                        toAdd.Y = Y;
                        toAdd.Z = Z;
                        toAdd.TemplateAreaId = template.AreaId;
                        toAdd.DungeonName = name;
                        toAdd.AreaExits.AddRange(template.AreaExits);
                        toAdd.AdjacentAreas.Add(adj.Key, adj.Value);
                        switch(adj.Key)
                        {
                            case ExitDirection.North:
                                adj.Value.AdjacentAreas.Add(ExitDirection.South, toAdd);
                                break;
                            case ExitDirection.South:
                                adj.Value.AdjacentAreas.Add(ExitDirection.North, toAdd);
                                break;
                            case ExitDirection.East:
                                adj.Value.AdjacentAreas.Add(ExitDirection.West, toAdd);
                                break;
                            case ExitDirection.West:
                                adj.Value.AdjacentAreas.Add(ExitDirection.East, toAdd);
                                break;
                            case ExitDirection.Up:
                                adj.Value.AdjacentAreas.Add(ExitDirection.Down, toAdd);
                                break;
                            case ExitDirection.Down:
                                adj.Value.AdjacentAreas.Add(ExitDirection.Up, toAdd);
                                break;
                        }
                        areasToGenerate -= (toAdd.AreaExits.Count - toAdd.AdjacentAreas.Count);
                        AreasOfDungeon.Add(toAdd);
                        areasNeedingAdjacentAreas.Add(toAdd);
                    }
                }
            }
        }
 private void _buildBorders(Dictionary<ExitDirection, bool> necessaryBorders, Dictionary<ExitDirection, RandomDungeonArea> adjacentToBe, RandomDungeonArea toAdd)
 {
     foreach (RandomDungeonArea area in AreasOfDungeon)
     {
         if (area.X == toAdd.X && area.Y == toAdd.Y && area.Z == toAdd.Z + 1)
         {
             // Area is above the new area.
             if (area.AreaExits.Contains(ExitDirection.Down))
             {
                 necessaryBorders.Add(ExitDirection.Up, true);
                 adjacentToBe.Add(ExitDirection.Up, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.Up))
             {
                 // This location might have double end caps in it.
                 necessaryBorders.Add(ExitDirection.Up, false);
             }
         }
         else if (area.X == toAdd.X && area.Y == toAdd.Y && area.Z == toAdd.Z - 1)
         {
             if (area.AreaExits.Contains(ExitDirection.Up))
             {
                 necessaryBorders.Add(ExitDirection.Down, true);
                 adjacentToBe.Add(ExitDirection.Down, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.Down))
             {
                 necessaryBorders.Add(ExitDirection.Down, false);
             }
         }
         else if (area.X == toAdd.X + 1 && area.Y == toAdd.Y && area.Z == toAdd.Z)
         {
             if (area.AreaExits.Contains(ExitDirection.West))
             {
                 necessaryBorders.Add(ExitDirection.East, true);
                 adjacentToBe.Add(ExitDirection.East, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.East))
             {
                 necessaryBorders.Add(ExitDirection.East, false);
             }
         }
         else if (area.X == toAdd.X - 1 && area.Y == toAdd.Y && area.Z == toAdd.Z)
         {
             if (area.AreaExits.Contains(ExitDirection.East))
             {
                 necessaryBorders.Add(ExitDirection.West, true);
                 adjacentToBe.Add(ExitDirection.West, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.West))
             {
                 necessaryBorders.Add(ExitDirection.West, false);
             }
         }
         else if (area.X == toAdd.X && area.Y == toAdd.Y + 1 && area.Z == toAdd.Z)
         {
             if (area.AreaExits.Contains(ExitDirection.South))
             {
                 necessaryBorders.Add(ExitDirection.North, true);
                 adjacentToBe.Add(ExitDirection.North, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.North))
             {
                 necessaryBorders.Add(ExitDirection.North, false);
             }
         }
         else if (area.X == toAdd.X && area.Y == toAdd.Y - 1 && area.Z == toAdd.Z)
         {
             if (area.AreaExits.Contains(ExitDirection.North))
             {
                 necessaryBorders.Add(ExitDirection.South, true);
                 adjacentToBe.Add(ExitDirection.South, area);
             }
             else if (!necessaryBorders.ContainsKey(ExitDirection.South))
             {
                 necessaryBorders.Add(ExitDirection.South, false);
             }
         }
     }
 }