예제 #1
0
        protected MobSpawn GetSeedChar(BaseMapGenContext map, SpawnList <MobSpawn> specialMobs)
        {
            //the contents of that theme can be selected randomly,
            MobSpawn seedSpawn = null;

            //or, to add some sensibility, make it seeded from a random spawn that can already be found in the map
            if (map.TeamSpawns.CanPick)
            {
                TeamSpawner spawn = map.TeamSpawns.Pick(map.Rand);
                if (spawn != null)
                {
                    List <MobSpawn> exampleList = spawn.ChooseSpawns(map.Rand);
                    if (exampleList.Count > 0)
                    {
                        seedSpawn = exampleList[map.Rand.Next(exampleList.Count)];
                    }
                }
            }
            //choose the spawn, then seed the theme with it
            //the theme will take the aspects of the seedspawn and then be ready to spit out a list
            if (seedSpawn == null && specialMobs.CanPick)
            {
                seedSpawn = specialMobs.Pick(map.Rand);
            }
            return(seedSpawn);
        }
예제 #2
0
        public override void Apply(ZoneGenContext zoneContext, IGenContext context, StablePriorityQueue <Priority, IGenStep> queue)
        {
            //find the first postproc that is a GridRoom postproc and add this to its special rooms
            //NOTE: if a room-based generator is not found as the generation step, it will just skip this floor but treat it as though it was placed.
            if (SpreadPlan.CheckIfDistributed(zoneContext, context))
            {
                //TODO: allow arbitrary components to be added
                RoomGenOption genDuo = Spawns.Pick(context.Rand);
                SetGridSpecialRoomStep <MapGenContext> specialStep     = new SetGridSpecialRoomStep <MapGenContext>();
                SetSpecialRoomStep <ListMapGenContext> listSpecialStep = new SetSpecialRoomStep <ListMapGenContext>();

                specialStep.Filters = genDuo.Filters;
                if (specialStep.CanApply(context))
                {
                    specialStep.Rooms = new PresetPicker <RoomGen <MapGenContext> >(genDuo.GridOption);
                    specialStep.RoomComponents.Set(new ImmutableRoom());
                    queue.Enqueue(PriorityGrid, specialStep);
                }
                else if (listSpecialStep.CanApply(context))
                {
                    listSpecialStep.Rooms = new PresetPicker <RoomGen <ListMapGenContext> >(genDuo.ListOption);
                    listSpecialStep.RoomComponents.Set(new ImmutableRoom());
                    PresetPicker <PermissiveRoomGen <ListMapGenContext> > picker = new PresetPicker <PermissiveRoomGen <ListMapGenContext> >();
                    picker.ToSpawn        = new RoomGenAngledHall <ListMapGenContext>(0);
                    listSpecialStep.Halls = picker;
                    queue.Enqueue(PriorityList, listSpecialStep);
                }
            }
        }
예제 #3
0
        private void addToQueue(ZoneGenContext zoneContext, IGenContext context, StablePriorityQueue <Priority, IGenStep> queue)
        {
            int id = zoneContext.CurrentID;

            IMonsterHouseBaseStep monsterHouseStep = HouseStepSpawns.Pick(context.Rand).CreateNew();
            SpawnList <MapItem>   itemListSlice    = Items.GetSpawnList(id);

            for (int jj = 0; jj < itemListSlice.Count; jj++)
            {
                monsterHouseStep.Items.Add(new MapItem(itemListSlice.GetSpawn(jj)), itemListSlice.GetSpawnRate(jj));
            }
            SpawnList <ItemTheme> itemThemeListSlice = ItemThemes.GetSpawnList(id);

            for (int jj = 0; jj < itemThemeListSlice.Count; jj++)
            {
                monsterHouseStep.ItemThemes.Add(itemThemeListSlice.GetSpawn(jj).Copy(), itemThemeListSlice.GetSpawnRate(jj));
            }
            SpawnList <MobSpawn> mobListSlice = Mobs.GetSpawnList(id);

            for (int jj = 0; jj < mobListSlice.Count; jj++)
            {
                MobSpawn newSpawn = mobListSlice.GetSpawn(jj).Copy();
                monsterHouseStep.Mobs.Add(newSpawn, mobListSlice.GetSpawnRate(jj));
            }
            SpawnList <MobTheme> mobThemeListSlice = MobThemes.GetSpawnList(id);

            for (int jj = 0; jj < mobThemeListSlice.Count; jj++)
            {
                monsterHouseStep.MobThemes.Add(mobThemeListSlice.GetSpawn(jj).Copy(), mobThemeListSlice.GetSpawnRate(jj));
            }

            queue.Enqueue(Priority, monsterHouseStep);
        }
예제 #4
0
        public override void Apply(T map)
        {
            int chosenAmount = Amount.Pick(map.Rand);

            if (chosenAmount > 0 && Spawns.Count > 0 && PatternSpawns.Count > 0)
            {
                List <int> openRooms = new List <int>();
                //get all places that traps are eligible
                for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++)
                {
                    if (BaseRoomFilter.PassesAllFilters(map.RoomPlan.GetRoomPlan(ii), this.Filters))
                    {
                        openRooms.Add(ii);
                    }
                }

                for (int ii = 0; ii < chosenAmount; ii++)
                {
                    // add traps
                    if (openRooms.Count > 0)
                    {
                        int         randIndex = map.Rand.Next(openRooms.Count);
                        TrapPattern pattern   = PatternSpawns.Pick(map.Rand);
                    }
                }
            }
        }
예제 #5
0
 public override void Apply(ZoneGenContext zoneContext, IGenContext context, StablePriorityQueue <Priority, IGenStep> queue)
 {
     if (SpreadPlan.CheckIfDistributed(zoneContext, context))
     {
         IGenPriority genStep = Spawns.Pick(context.Rand);
         queue.Enqueue(genStep.Priority, genStep.GetItem());
     }
 }
예제 #6
0
        public override void ApplyFeature(IMobSpawnMap map, Character newChar)
        {
            if (MapStartOnly && map.Begun)
            {
                return;
            }

            newChar.EquippedItem = Items.Pick(map.Rand);
        }
        public void SpawnListEmptyChoose()
        {
            // choose when empty
            var            spawnList = new SpawnList <string>();
            Mock <IRandom> testRand  = new Mock <IRandom>(MockBehavior.Strict);

            Assert.That(spawnList.CanPick, Is.EqualTo(false));
            Assert.Throws <InvalidOperationException>(() => { spawnList.Pick(testRand.Object); });
        }
예제 #8
0
        public override List <MapItem> GenerateItems(BaseMapGenContext map, SpawnList <MapItem> specialItems)
        {
            int            itemCount = Amount.Pick(map.Rand);
            List <MapItem> spawners  = new List <MapItem>();

            SpawnList <MapItem> subList = new SpawnList <MapItem>();

            if (UseSpecialItems)
            {
                for (int ii = 0; ii < specialItems.Count; ii++)
                {
                    MapItem spawn = specialItems.GetSpawn(ii);
                    if (!spawn.IsMoney)
                    {
                        ItemEntrySummary itemEntry = DataManager.Instance.DataIndices[DataManager.DataType.Item].Entries[spawn.Value] as ItemEntrySummary;

                        if (itemEntry.UsageType == UseType)
                        {
                            subList.Add(spawn, specialItems.GetSpawnRate(ii));
                        }
                    }
                }
            }

            if (UseMapItems)
            {
                foreach (string key in map.ItemSpawns.Spawns.GetKeys())
                {
                    SpawnList <InvItem> spawns = map.ItemSpawns.Spawns.GetSpawn(key);
                    for (int ii = 0; ii < spawns.Count; ii++)
                    {
                        //TODO: spawn rate is somewhat distorted here
                        InvItem          spawn     = spawns.GetSpawn(ii);
                        ItemEntrySummary itemEntry = DataManager.Instance.DataIndices[DataManager.DataType.Item].Entries[spawn.ID] as ItemEntrySummary;
                        if (itemEntry.UsageType == UseType)
                        {
                            subList.Add(new MapItem(spawn), spawns.GetSpawnRate(ii));
                        }
                    }
                }
            }

            if (subList.Count == 0)
            {
                return(spawners);
            }

            for (int ii = 0; ii < itemCount; ii++)
            {
                spawners.Add(subList.Pick(map.Rand));
            }

            return(spawners);
        }
예제 #9
0
        public override List <MapItem> GenerateItems(BaseMapGenContext map, SpawnList <MapItem> specialItems)
        {
            int            itemCount = Amount.Pick(map.Rand);
            List <MapItem> spawners  = new List <MapItem>();

            SpawnList <MapItem> subList = new SpawnList <MapItem>();

            if (UseSpecialItems)
            {
                for (int ii = 0; ii < specialItems.Count; ii++)
                {
                    MapItem spawn = specialItems.GetSpawn(ii);
                    if (!spawn.IsMoney)
                    {
                        if (Range.Min <= spawn.Value && spawn.Value < Range.Max)
                        {
                            subList.Add(spawn, specialItems.GetSpawnRate(ii));
                        }
                    }
                }
            }

            if (UseMapItems)
            {
                foreach (string key in map.ItemSpawns.Spawns.GetKeys())
                {
                    SpawnList <InvItem> spawns = map.ItemSpawns.Spawns.GetSpawn(key);
                    for (int ii = 0; ii < spawns.Count; ii++)
                    {
                        //TODO: spawn rate is somewhat distorted here
                        InvItem spawn = spawns.GetSpawn(ii);
                        //ItemData data = DataManager.Instance.GetItem(spawn.ID);
                        if (Range.Min <= spawn.ID && spawn.ID < Range.Max)
                        {
                            subList.Add(new MapItem(spawn), spawns.GetSpawnRate(ii));
                        }
                    }
                }
            }

            if (subList.Count == 0)
            {
                return(spawners);
            }

            for (int ii = 0; ii < itemCount; ii++)
            {
                spawners.Add(subList.Pick(map.Rand));
            }

            return(spawners);
        }
예제 #10
0
        public override void ApplyFeature(IMobSpawnMap map, Character newChar)
        {
            StatusEffect status = Statuses.Pick(map.Rand).Clone();//Clone Use Case; convert to Instantiate?

            status.LoadFromData();
            StatusData entry = (StatusData)status.GetData();

            if (!entry.Targeted)//no targeted statuses allowed
            {
                //need to also add the additional status states
                newChar.StatusEffects.Add(status.ID, status);
            }
        }
예제 #11
0
        public override void Apply(ZoneGenContext zoneContext, IGenContext context, StablePriorityQueue <Priority, IGenStep> queue)
        {
            int id = zoneContext.CurrentID;

            foreach (int floorId in SpreadPlan.DropPoints)
            {
                if (floorId != zoneContext.CurrentID)
                {
                    continue;
                }
                foreach (IGenPriority vaultStep in VaultSteps)
                {
                    queue.Enqueue(vaultStep.Priority, vaultStep.GetItem());
                }

                {
                    SpawnList <MapItem> itemListSlice = Items.GetSpawnList(id);
                    PickerSpawner <ListMapGenContext, MapItem> constructedSpawns = new PickerSpawner <ListMapGenContext, MapItem>(new LoopedRand <MapItem>(itemListSlice, ItemAmount[id]));

                    List <IStepSpawner <ListMapGenContext, MapItem> > steps = new List <IStepSpawner <ListMapGenContext, MapItem> >();
                    steps.Add(constructedSpawns);
                    if (ItemSpawners.ContainsItem(id))
                    {
                        IStepSpawner <ListMapGenContext, MapItem> treasures = ItemSpawners[id].Copy();
                        steps.Add(treasures);
                    }
                    PresetMultiRand <IStepSpawner <ListMapGenContext, MapItem> > groupRand   = new PresetMultiRand <IStepSpawner <ListMapGenContext, MapItem> >(steps.ToArray());
                    RandomRoomSpawnStep <ListMapGenContext, MapItem>             detourItems = ItemPlacements[id].Copy();
                    detourItems.Spawn = new MultiStepSpawner <ListMapGenContext, MapItem>(groupRand);
                    queue.Enqueue(ItemPriority, detourItems);
                }


                SpawnList <MobSpawn> mobListSlice = Mobs.GetSpawnList(id);
                if (mobListSlice.CanPick)
                {
                    //secret enemies
                    SpecificTeamSpawner specificTeam = new SpecificTeamSpawner();

                    MobSpawn newSpawn = mobListSlice.Pick(context.Rand).Copy();
                    specificTeam.Spawns.Add(newSpawn);

                    //use bruteforce clone for this
                    PlaceRandomMobsStep <ListMapGenContext> secretMobPlacement = MobPlacements[id].Copy();
                    secretMobPlacement.Spawn = new LoopedTeamSpawner <ListMapGenContext>(specificTeam, MobAmount[id]);
                    queue.Enqueue(MobPriority, secretMobPlacement);
                }
            }
        }
예제 #12
0
        public List <TSpawnable> GetSpawns(TGenContext map)
        {
            List <TSpawnable> spawns = new List <TSpawnable>();

            foreach (TSpawnable element in SpecificSpawns)
            {
                spawns.Add(element);
            }
            for (int ii = 0; ii < SpawnAmount; ii++)
            {
                spawns.Add(RandomSpawns.Pick(map.Rand));
            }

            return(spawns);
        }
예제 #13
0
        public override List <MapItem> GenerateItems(BaseMapGenContext map, SpawnList <MapItem> specialItems)
        {
            int            itemCount = Amount.Pick(map.Rand);
            List <MapItem> spawners  = new List <MapItem>();

            for (int ii = 0; ii < itemCount; ii++)
            {
                if (specialItems.Count > 0 && map.Rand.Next(100) < SpecialRatio)
                {
                    spawners.Add(specialItems.Pick(map.Rand));
                }
                else if (map.ItemSpawns.CanPick)
                {
                    spawners.Add(new MapItem(map.ItemSpawns.Pick(map.Rand)));
                }
            }

            return(spawners);
        }
예제 #14
0
        public override void Apply(ZoneGenContext zoneContext, IGenContext context, StablePriorityQueue <Priority, IGenStep> queue)
        {
            int id = zoneContext.CurrentID;

            foreach (int floorId in SpreadPlan.DropPoints)
            {
                if (floorId != zoneContext.CurrentID)
                {
                    continue;
                }
                {
                    SpawnList <AddBossRoomStep <ListMapGenContext> > bossListSlice = BossSteps.GetSpawnList(id);
                    if (!bossListSlice.CanPick)
                    {
                        return;
                    }
                    AddBossRoomStep <ListMapGenContext> bossStep = bossListSlice.Pick(context.Rand).Copy();
                    queue.Enqueue(BossRoomPriority, bossStep);
                }

                foreach (IGenPriority vaultStep in VaultSteps)
                {
                    queue.Enqueue(vaultStep.Priority, vaultStep.GetItem());
                }

                {
                    SpawnList <MapItem> itemListSlice = Items.GetSpawnList(id);
                    PickerSpawner <ListMapGenContext, MapItem> constructedSpawns = new PickerSpawner <ListMapGenContext, MapItem>(new LoopedRand <MapItem>(itemListSlice, ItemAmount[id]));

                    IStepSpawner <ListMapGenContext, MapItem> treasures = ItemSpawners[id].Copy();

                    PresetMultiRand <IStepSpawner <ListMapGenContext, MapItem> > groupRand = new PresetMultiRand <IStepSpawner <ListMapGenContext, MapItem> >(constructedSpawns, treasures);

                    RandomRoomSpawnStep <ListMapGenContext, MapItem> detourItems = ItemPlacements[id].Copy();
                    detourItems.Spawn = new MultiStepSpawner <ListMapGenContext, MapItem>(groupRand);
                    queue.Enqueue(RewardPriority, detourItems);
                }
            }
        }
예제 #15
0
        public override List <MobSpawn> GenerateMobs(BaseMapGenContext map, SpawnList <MobSpawn> specialMobs)
        {
            int                  mobCount = Amount.Pick(map.Rand);
            List <MobSpawn>      spawners = new List <MobSpawn>();
            IEnumerable <int>    species  = GetSpecies(map, specialMobs);
            SpawnList <MobSpawn> subList  = new SpawnList <MobSpawn>();

            for (int ii = 0; ii < specialMobs.Count; ii++)
            {
                MobSpawn spawn = specialMobs.GetSpawn(ii);
                if (CheckIfAllowed(map, spawn, species))
                {
                    subList.Add(spawn, specialMobs.GetSpawnRate(ii));
                }
            }
            for (int ii = 0; ii < map.TeamSpawns.Count; ii++)
            {
                SpawnList <MobSpawn> memberSpawns = map.TeamSpawns.GetSpawn(ii).GetPossibleSpawns();
                for (int jj = 0; ii < memberSpawns.Count; jj++)
                {
                    MobSpawn spawn = memberSpawns.GetSpawn(jj);
                    if (CheckIfAllowed(map, spawn, species))
                    {
                        subList.Add(spawn, memberSpawns.GetSpawnRate(jj));
                    }
                }
            }

            if (subList.Count > 0)
            {
                for (int ii = 0; ii < mobCount; ii++)
                {
                    spawners.Add(subList.Pick(map.Rand));
                }
            }

            return(spawners);
        }
예제 #16
0
        public override List <MobSpawn> GenerateMobs(BaseMapGenContext map, SpawnList <MobSpawn> specialMobs)
        {
            int             mobCount = Amount.Pick(map.Rand);
            List <MobSpawn> spawners = new List <MobSpawn>();

            for (int ii = 0; ii < mobCount; ii++)
            {
                if (specialMobs.Count > 0 && map.Rand.Next(100) < SpecialRatio)
                {
                    spawners.Add(specialMobs.Pick(map.Rand));
                }
                else if (map.TeamSpawns.CanPick)
                {
                    List <MobSpawn> exampleList = map.TeamSpawns.Pick(map.Rand).ChooseSpawns(map.Rand);
                    if (exampleList.Count > 0)
                    {
                        spawners.Add(exampleList[map.Rand.Next(exampleList.Count)]);
                    }
                }
            }

            return(spawners);
        }
예제 #17
0
        public List <Character> RespawnMob()
        {
            List <Character> respawns = new List <Character>();

            if (TeamSpawns.Count > 0)
            {
                bool[][] traversedGrid = new bool[Width][];
                for (int xx = 0; xx < Width; xx++)
                {
                    traversedGrid[xx] = new bool[Height];
                }

                List <Loc> freeTiles = new List <Loc>();
                Grid.FloodFill(new Rect(new Loc(), new Loc(Width, Height)),
                               (Loc testLoc) =>
                {
                    if (traversedGrid[testLoc.X][testLoc.Y])
                    {
                        return(true);
                    }
                    return(TileBlocked(testLoc));
                },
                               (Loc testLoc) =>
                {
                    if (traversedGrid[testLoc.X][testLoc.Y])
                    {
                        return(true);
                    }
                    return(TileBlocked(testLoc, true));
                },
                               (Loc testLoc) =>
                {
                    traversedGrid[testLoc.X][testLoc.Y] = true;

                    //must be walkable, not have a nonwalkable on at least 3 cardinal directions, not be within eyesight of any of the player characters
                    foreach (Character character in ActiveTeam.Players)
                    {
                        if (character.IsInSightBounds(testLoc))
                        {
                            return;
                        }
                    }

                    foreach (Team team in MapTeams)
                    {
                        foreach (Character character in team.Players)
                        {
                            if (!character.Dead && character.CharLoc == testLoc)
                            {
                                return;
                            }
                        }
                    }
                    freeTiles.Add(testLoc);
                },
                               EntryPoints[0].Loc);

                if (freeTiles.Count > 0)
                {
                    for (int ii = 0; ii < 10; ii++)
                    {
                        Team newTeam = TeamSpawns.Pick(Rand).Spawn(this);
                        if (newTeam == null)
                        {
                            continue;
                        }
                        Loc trialLoc = freeTiles[Rand.Next(freeTiles.Count)];
                        //find a way to place all members- needs to fit all of them in, or else fail the spawn

                        Grid.LocTest checkOpen = (Loc testLoc) =>
                        {
                            if (TileBlocked(testLoc))
                            {
                                return(false);
                            }

                            Character locChar = GetCharAtLoc(testLoc);
                            if (locChar != null)
                            {
                                return(false);
                            }
                            return(true);
                        };
                        Grid.LocTest checkBlock = (Loc testLoc) =>
                        {
                            return(TileBlocked(testLoc, true));
                        };
                        Grid.LocTest checkDiagBlock = (Loc testLoc) =>
                        {
                            return(TileBlocked(testLoc, true, true));
                        };

                        List <Loc> resultLocs = new List <Loc>();
                        foreach (Loc loc in Grid.FindClosestConnectedTiles(new Loc(), new Loc(Width, Height),
                                                                           checkOpen, checkBlock, checkDiagBlock, trialLoc, newTeam.Players.Count))
                        {
                            resultLocs.Add(loc);
                        }


                        if (resultLocs.Count >= newTeam.Players.Count)
                        {
                            for (int jj = 0; jj < newTeam.Players.Count; jj++)
                            {
                                newTeam.Players[jj].CharLoc = resultLocs[jj];
                            }

                            MapTeams.Add(newTeam);

                            foreach (Character member in newTeam.Players)
                            {
                                member.RefreshTraits();
                                respawns.Add(member);
                            }
                            break;
                        }
                    }
                }
            }
            return(respawns);
        }
예제 #18
0
        protected LocRay4?PlaceRoom(T map, List <LocRay4> rays, EffectTile sealingTile, List <Loc> freeTiles)
        {
            Grid.LocTest checkBlockForPlace = (Loc testLoc) =>
            {
                if (!Collision.InBounds(map.Width, map.Height, testLoc))
                {
                    return(false);
                }
                return(!map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.RoomTerrain) && !map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.UnbreakableTerrain));
            };
            //try X times to dig a passage
            for (int ii = 0; ii < 500 && rays.Count > 0; ii++)
            {
                int     rayIndex = map.Rand.Next(rays.Count);
                LocRay4 ray      = rays[rayIndex];
                rays.RemoveAt(rayIndex);

                Loc   rayDirLoc = ray.Dir.GetLoc();
                Axis4 axis      = ray.Dir.ToAxis();
                Axis4 orth      = axis == Axis4.Horiz ? Axis4.Vert : Axis4.Horiz;

                int  minLength = Math.Max(1, HallLength.Min);
                Rect hallBound = new Rect(ray.Loc + DirExt.AddAngles(ray.Dir, Dir4.Left).GetLoc(), new Loc(1));
                hallBound = Rect.IncludeLoc(hallBound, ray.Loc + rayDirLoc * (minLength - 1) + DirExt.AddAngles(ray.Dir, Dir4.Right).GetLoc());

                //make sure the MIN hall can tunnel unimpeded
                if (!CanPlaceRect(map, hallBound, checkBlockForPlace))
                {
                    continue;
                }

                for (int jj = 0; jj < 100; jj++)
                {
                    //plan the room
                    RoomGen <T> plan = GenericRooms.Pick(map.Rand).Copy();
                    Loc         size = plan.ProposeSize(map.Rand);
                    plan.PrepareSize(map.Rand, size);
                    //attempt to place the bounds somewhere, anywhere, within the limitations that the room itself provides
                    List <int> candidateOpenings = new List <int>();
                    int        planLength        = plan.GetBorderLength(ray.Dir.Reverse());
                    for (int kk = 0; kk < planLength; kk++)
                    {
                        if (plan.GetFulfillableBorder(ray.Dir.Reverse(), kk))
                        {
                            candidateOpenings.Add(kk);
                        }
                    }

                    //as well as continue extending the hall until we hit a walkable.
                    int tunnelLen  = Math.Max(1, HallLength.Pick(map.Rand));
                    Loc roomLoc    = ray.Loc + rayDirLoc * tunnelLen;
                    int perpOffset = candidateOpenings[map.Rand.Next(candidateOpenings.Count)];
                    roomLoc += orth.CreateLoc(-perpOffset, 0);
                    if (rayDirLoc.GetScalar(axis) < 0)//move back the top-left of the entrance
                    {
                        roomLoc += rayDirLoc * (size.GetScalar(axis) - 1);
                    }

                    Rect roomTestBound = new Rect(roomLoc, size);
                    roomTestBound.Inflate(1, 1);
                    //make a rect for the rest of the hall
                    Rect hallExtBound = new Rect(ray.Loc + rayDirLoc * minLength + DirExt.AddAngles(ray.Dir, Dir4.Left).GetLoc(), new Loc(1));
                    hallExtBound = Rect.IncludeLoc(hallBound, ray.Loc + rayDirLoc * (tunnelLen - 1) + DirExt.AddAngles(ray.Dir, Dir4.Right).GetLoc());
                    //now that we've chosen our position, let's test it
                    if (!CanPlaceRect(map, roomTestBound, checkBlockForPlace) || !CanPlaceRect(map, hallExtBound, checkBlockForPlace)) // also test that the CHOSEN hallway can be properly sealed
                    {
                        continue;                                                                                                      //invalid location, try another place
                    }
                    else
                    {
                        plan.SetLoc(roomLoc);

                        plan.ReceiveBorderRange(new IntRange(perpOffset, perpOffset + 1) + roomLoc.GetScalar(orth), ray.Dir.Reverse());
                        //draw the room
                        plan.DrawOnMap(map);

                        //surround the room with bounds
                        for (int xx = roomTestBound.X; xx < roomTestBound.Right; xx++)
                        {
                            map.Tiles[xx][roomTestBound.Y]         = (Tile)map.UnbreakableTerrain.Copy();
                            map.Tiles[xx][roomTestBound.End.Y - 1] = (Tile)map.UnbreakableTerrain.Copy();
                        }
                        for (int yy = roomTestBound.Y + 1; yy < roomTestBound.Bottom - 1; yy++)
                        {
                            map.Tiles[roomTestBound.X][yy]         = (Tile)map.UnbreakableTerrain.Copy();
                            map.Tiles[roomTestBound.End.X - 1][yy] = (Tile)map.UnbreakableTerrain.Copy();
                        }

                        //spawn tiles, items, foes
                        List <Loc> addedTiles = ((IPlaceableGenContext <MapItem>)map).GetFreeTiles(plan.Draw);
                        freeTiles.AddRange(addedTiles);


                        //tunnel to the room
                        Loc loc = ray.Loc;
                        for (int tt = 0; tt < tunnelLen; tt++)
                        {
                            //make walkable
                            map.Tiles[loc.X][loc.Y] = (Tile)map.RoomTerrain.Copy();

                            //make left side unbreakable
                            Loc lLoc = loc + DirExt.AddAngles(ray.Dir, Dir4.Left).GetLoc();
                            map.Tiles[lLoc.X][lLoc.Y] = (Tile)map.UnbreakableTerrain.Copy();

                            //make right side unbreakable
                            Loc rLoc = loc + DirExt.AddAngles(ray.Dir, Dir4.Right).GetLoc();
                            map.Tiles[rLoc.X][rLoc.Y] = (Tile)map.UnbreakableTerrain.Copy();

                            loc += rayDirLoc;
                        }

                        //finally, seal with a locked door
                        map.Tiles[ray.Loc.X][ray.Loc.Y] = (Tile)map.UnbreakableTerrain.Copy();
                        EffectTile newEffect = new EffectTile(sealingTile, ray.Loc);
                        ((IPlaceableGenContext <EffectTile>)map).PlaceItem(ray.Loc, newEffect);

                        return(ray);
                    }
                }
            }

            //DiagManager.Instance.LogInfo("Couldn't place sealed detour!");

            return(null);
        }
예제 #19
0
        public override void DrawOnMap(T map)
        {
            Loc isleSize = new Loc(1);

            while (isleSize.X * isleSize.Y < ItemAmount)
            {
                if (isleSize.X > isleSize.Y)
                {
                    isleSize.Y++;
                }
                else
                {
                    isleSize.X++;
                }
            }

            //require at least a rectangle that can contain a ring of land around the ring of water
            if (isleSize.X + 4 > Draw.Size.X || isleSize.Y + 4 > Draw.Size.Y)
            {
                DrawMapDefault(map);
                return;
            }

            Loc ringSize = isleSize + new Loc(2);

            //size of room should be between size of cave + 2 and max
            for (int x = 0; x < Draw.Size.X; x++)
            {
                for (int y = 0; y < Draw.Size.Y; y++)
                {
                    map.SetTile(new Loc(Draw.X + x, Draw.Y + y), map.RoomTerrain.Copy());
                }
            }

            List <Loc> freeTiles  = new List <Loc>();
            Loc        blockStart = new Loc(Draw.X + 1 + map.Rand.Next(Draw.Size.X - ringSize.X - 1), Draw.Y + 1 + map.Rand.Next(Draw.Size.Y - ringSize.Y - 1));

            for (int x = 0; x < ringSize.X; x++)
            {
                for (int y = 0; y < ringSize.Y; y++)
                {
                    if (x == 0 || x == ringSize.X - 1 || y == 0 || y == ringSize.Y - 1)
                    {
                        map.SetTile(new Loc(blockStart.X + x, blockStart.Y + y), WaterTerrain.Copy());
                    }
                    else
                    {
                        freeTiles.Add(new Loc(blockStart.X + x, blockStart.Y + y));
                    }
                }
            }
            if (Treasures.Count > 0)
            {
                for (int ii = 0; ii < ItemAmount; ii++)
                {
                    MapItem item      = new MapItem(Treasures.Pick(map.Rand));
                    int     randIndex = map.Rand.Next(freeTiles.Count);
                    map.PlaceItem(freeTiles[randIndex], item);
                    freeTiles.RemoveAt(randIndex);
                }
            }

            //hall restrictions
            SetRoomBorders(map);
        }
예제 #20
0
        public override List <MobSpawn> ChooseSpawns(IRandom rand)
        {
            List <MobSpawn> chosenSpawns = new List <MobSpawn>();

            int teamSize = TeamSizes.Pick(rand);

            bool selectedLeader  = false;
            bool selectedSupport = false;

            //pick first team member
            List <SpawnList <MobSpawn> > eligibleSpawns = new List <SpawnList <MobSpawn> >
            {
                NormalSpawns, LeaderSpawns,
            };

            if (teamSize > 1)
            {
                eligibleSpawns.Add(SupportSpawns);
            }
            else
            {
                eligibleSpawns.Add(LonerSpawns);
            }

            SpawnList <MobSpawn> chosenList = chooseSpawnList(eligibleSpawns, rand);

            if (chosenList == LeaderSpawns)
            {
                selectedLeader = true;
            }
            else if (chosenList == SupportSpawns)
            {
                selectedSupport = true;
            }

            chosenSpawns.Add(chosenList.Pick(rand));

            //pick remaining team members
            for (int ii = 1; ii < teamSize; ii++)
            {
                eligibleSpawns = new List <SpawnList <MobSpawn> >();
                eligibleSpawns.Add(NormalSpawns);
                if (!selectedLeader)
                {
                    eligibleSpawns.Add(LeaderSpawns);
                }
                if (!selectedSupport)
                {
                    eligibleSpawns.Add(SupportSpawns);
                }


                chosenList = chooseSpawnList(eligibleSpawns, rand);
                if (chosenList == LeaderSpawns)
                {
                    selectedLeader = true;
                }
                else if (chosenList == SupportSpawns)
                {
                    selectedSupport = true;
                }

                chosenSpawns.Add(chosenList.Pick(rand));
            }

            return(chosenSpawns);
        }
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            for (int xx = 0; xx < floorPlan.GridWidth - 1; xx++)
            {
                for (int yy = 0; yy < floorPlan.GridHeight - 1; yy++)
                {
                    //check for room presence in all rooms (must be SINGLE and immutable)
                    if (!roomViable(floorPlan, xx, yy))
                    {
                        continue;
                    }
                    if (!roomViable(floorPlan, xx, yy + 1))
                    {
                        continue;
                    }
                    if (!roomViable(floorPlan, xx + 1, yy))
                    {
                        continue;
                    }
                    if (!roomViable(floorPlan, xx + 1, yy + 1))
                    {
                        continue;
                    }

                    //check for hall connectivity in all constituent halls
                    if (floorPlan.GetHall(new LocRay4(xx, yy, Dir4.Down)) == null)
                    {
                        continue;
                    }
                    if (floorPlan.GetHall(new LocRay4(xx, yy, Dir4.Right)) == null)
                    {
                        continue;
                    }
                    if (floorPlan.GetHall(new LocRay4(xx + 1, yy, Dir4.Down)) == null)
                    {
                        continue;
                    }
                    if (floorPlan.GetHall(new LocRay4(xx, yy + 1, Dir4.Right)) == null)
                    {
                        continue;
                    }

                    if (rand.Next(100) < CombineChance)
                    {
                        //erase the constituent rooms
                        floorPlan.EraseRoom(new Loc(xx, yy));
                        floorPlan.EraseRoom(new Loc(xx + 1, yy));
                        floorPlan.EraseRoom(new Loc(xx, yy + 1));
                        floorPlan.EraseRoom(new Loc(xx + 1, yy + 1));

                        //erase the constituent halls
                        floorPlan.SetHall(new LocRay4(xx, yy, Dir4.Down), null, new ComponentCollection());
                        floorPlan.SetHall(new LocRay4(xx, yy, Dir4.Right), null, new ComponentCollection());
                        floorPlan.SetHall(new LocRay4(xx + 1, yy, Dir4.Down), null, new ComponentCollection());
                        floorPlan.SetHall(new LocRay4(xx, yy + 1, Dir4.Right), null, new ComponentCollection());

                        //place the room
                        RoomGen <T> gen = GiantRooms.Pick(rand);
                        floorPlan.AddRoom(new Rect(xx, yy, 2, 2), gen.Copy(), this.RoomComponents.Clone(), false);
                    }
                }
            }
        }
예제 #22
0
        public override void Apply(T map)
        {
            if (Spawns.Count > 0)
            {
                List <Loc> freeTiles = new List <Loc>();
                //get all places that traps are eligible
                for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++)
                {
                    IRoomGen room = map.RoomPlan.GetRoom(ii);

                    List <Loc> tiles = ((IPlaceableGenContext <EffectTile>)map).GetFreeTiles(room.Draw);

                    freeTiles.AddRange(tiles);
                }

                // add tile
                if (freeTiles.Count > 0)
                {
                    int        randIndex   = ((IGenContext)map).Rand.Next(freeTiles.Count);
                    Loc        loc         = freeTiles[randIndex];
                    EffectTile spawnedTrap = Spawns.Pick(((IGenContext)map).Rand);
                    map.PlaceItem(loc, spawnedTrap);
                    freeTiles.RemoveAt(randIndex);

                    if (GuardSpawns.Count > 0)
                    {
                        for (int ii = 0; ii < 10; ii++)
                        {
                            Team newTeam = GuardSpawns.Pick(((IGenContext)map).Rand).Spawn(map);
                            if (newTeam == null)
                            {
                                continue;
                            }
                            //spawn guards

                            Grid.LocTest checkSpawnOpen = (Loc testLoc) =>
                            {
                                return(((IGroupPlaceableGenContext <Team>)map).CanPlaceItem(testLoc));
                            };
                            Grid.LocTest checkSpawnBlock = (Loc testLoc) =>
                            {
                                return(map.TileBlocked(testLoc));
                            };
                            Grid.LocTest checkDiagSpawnBlock = (Loc testLoc) =>
                            {
                                return(map.TileBlocked(testLoc, true));
                            };

                            List <Loc> resultLocs = new List <Loc>();
                            foreach (Loc resultLoc in Grid.FindClosestConnectedTiles(new Loc(), new Loc(map.Width, map.Height),
                                                                                     checkSpawnOpen, checkSpawnBlock, checkDiagSpawnBlock, loc, newTeam.MemberGuestCount))
                            {
                                resultLocs.Add(resultLoc);
                            }

                            if (resultLocs.Count >= newTeam.MemberGuestCount)
                            {
                                Loc[] locs = new Loc[newTeam.MemberGuestCount];
                                for (int jj = 0; jj < locs.Length; jj++)
                                {
                                    locs[jj] = resultLocs[jj];
                                }
                                map.PlaceItems(newTeam, locs);
                                break;
                            }
                        }
                    }
                }
            }
        }
예제 #23
0
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            int chosenBigRooms = RoomAmount.Pick(rand);

            for (int ii = 0; ii < chosenBigRooms; ii++)
            {
                for (int jj = 0; jj < 20; jj++)
                {
                    LargeRoom <T> chosenRoom = GiantRooms.Pick(rand);
                    Rect          destRect   = new Rect(new Loc(rand.Next(floorPlan.GridWidth - chosenRoom.Size.X), rand.Next(floorPlan.GridHeight - chosenRoom.Size.Y)), chosenRoom.Size);
                    if (spaceViable(floorPlan, destRect))
                    {
                        List <LocRay4> raysOut = new List <LocRay4>();
                        for (int xx = destRect.Start.X; xx < destRect.End.X; xx++)
                        {
                            LocRay4 locUp = new LocRay4(xx, destRect.Start.Y, Dir4.Up);
                            if (destRect.Start.Y > 0 && floorPlan.GetHall(locUp) != null)
                            {
                                raysOut.Add(locUp);
                            }
                            LocRay4 locDown = new LocRay4(xx, destRect.Start.Y + chosenRoom.Size.Y - 1, Dir4.Down);
                            if (destRect.Start.Y < floorPlan.GridHeight - 1 && floorPlan.GetHall(locDown) != null)
                            {
                                raysOut.Add(locDown);
                            }
                        }
                        for (int yy = destRect.Start.Y; yy < destRect.End.Y; yy++)
                        {
                            LocRay4 locLeft = new LocRay4(destRect.Start.X, yy, Dir4.Left);
                            if (destRect.Start.X > 0 && floorPlan.GetHall(locLeft) != null)
                            {
                                raysOut.Add(locLeft);
                            }
                            LocRay4 locRight = new LocRay4(destRect.Start.X + chosenRoom.Size.X - 1, yy, Dir4.Right);
                            if (destRect.Start.X < floorPlan.GridWidth - 1 && floorPlan.GetHall(locRight) != null)
                            {
                                raysOut.Add(locRight);
                            }
                        }

                        List <List <LocRay4> > exitSets = findHallSets(floorPlan, destRect, raysOut);

                        //exits: no more than allowed
                        if (exitSets.Count > chosenRoom.AllowedEntrances)
                        {
                            continue;
                        }

                        //this block tallies all sets that can be joined to the big room
                        //it also chooses which ones to keep by randomly removing them from the raysOut list
                        int setsTaken = 0;
                        foreach (List <LocRay4> set in exitSets)
                        {
                            List <LocRay4> possibleRays = new List <LocRay4>();
                            foreach (LocRay4 ray in set)
                            {
                                int scalar = (ray.Loc - destRect.Start).GetScalar(ray.Dir.ToAxis().Orth());
                                if (chosenRoom.OpenBorders[(int)ray.Dir][scalar])
                                {
                                    possibleRays.Add(ray);
                                }
                            }
                            if (possibleRays.Count > 0)
                            {
                                LocRay4 locRay = possibleRays[rand.Next(possibleRays.Count)];
                                raysOut.Remove(locRay);
                                setsTaken++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        if (setsTaken == exitSets.Count)
                        {
                            for (int xx = 0; xx < chosenRoom.Size.X; xx++)
                            {
                                for (int yy = 0; yy < chosenRoom.Size.Y; yy++)
                                {
                                    //erase rooms in vicinity
                                    Loc loc = new Loc(xx + destRect.Start.X, yy + destRect.Start.Y);
                                    //erase halls in vicinity
                                    floorPlan.EraseRoom(loc);
                                    if (xx > 0)
                                    {
                                        floorPlan.SetHall(new LocRay4(loc, Dir4.Left), null, new ComponentCollection());
                                    }
                                    if (yy > 0)
                                    {
                                        floorPlan.SetHall(new LocRay4(loc, Dir4.Up), null, new ComponentCollection());
                                    }
                                }
                            }

                            //remove all halls still in the list
                            foreach (LocRay4 rayOut in raysOut)
                            {
                                floorPlan.SetHall(rayOut, null, new ComponentCollection());
                            }


                            //add room
                            floorPlan.AddRoom(destRect, chosenRoom.Gen, new ComponentCollection());

                            break;
                        }
                    }
                }
            }
        }
예제 #24
0
        public override List <MobSpawn> ChooseSpawns(IRandom rand)
        {
            List <MobSpawn> chosenSpawns = new List <MobSpawn>();

            if (!TeamSizes.CanPick)
            {
                return(chosenSpawns);
            }
            int teamSize = TeamSizes.Pick(rand);

            bool selectedLeader     = false;
            bool selectedNonSupport = false;

            //pick first team member
            SpawnList <TeamMemberSpawn> eligibleSpawns = new SpawnList <TeamMemberSpawn>();

            for (int ii = 0; ii < Spawns.Count; ii++)
            {
                TeamMemberSpawn spawn = Spawns.GetSpawn(ii);
                bool            add   = false;
                switch (spawn.Role)
                {
                case TeamMemberSpawn.MemberRole.Normal:
                case TeamMemberSpawn.MemberRole.Leader:
                    add = true;
                    break;

                case TeamMemberSpawn.MemberRole.Support:
                    add = (teamSize > 1);
                    break;

                case TeamMemberSpawn.MemberRole.Loner:
                    add = (teamSize == 1);
                    break;
                }
                if (add)
                {
                    eligibleSpawns.Add(spawn, Spawns.GetSpawnRate(ii));
                }
            }

            if (!eligibleSpawns.CanPick)
            {
                return(chosenSpawns);
            }
            TeamMemberSpawn chosenSpawn = eligibleSpawns.Pick(rand);

            if (chosenSpawn.Role == TeamMemberSpawn.MemberRole.Leader)
            {
                selectedLeader = true;
            }
            if (chosenSpawn.Role != TeamMemberSpawn.MemberRole.Support)
            {
                selectedNonSupport = true;
            }

            chosenSpawns.Add(chosenSpawn.Spawn);

            //pick remaining team members
            for (int jj = 1; jj < teamSize; jj++)
            {
                eligibleSpawns.Clear();

                for (int ii = 0; ii < Spawns.Count; ii++)
                {
                    TeamMemberSpawn spawn = Spawns.GetSpawn(ii);
                    bool            add   = false;
                    switch (spawn.Role)
                    {
                    case TeamMemberSpawn.MemberRole.Normal:
                        add = true;
                        break;

                    case TeamMemberSpawn.MemberRole.Leader:
                        add = !selectedLeader;
                        break;

                    case TeamMemberSpawn.MemberRole.Support:
                        add = selectedNonSupport;
                        break;
                    }
                    if (add)
                    {
                        eligibleSpawns.Add(spawn, Spawns.GetSpawnRate(ii));
                    }
                }

                if (!eligibleSpawns.CanPick)
                {
                    return(chosenSpawns);
                }
                chosenSpawn = eligibleSpawns.Pick(rand);
                if (chosenSpawn.Role == TeamMemberSpawn.MemberRole.Leader)
                {
                    selectedLeader = true;
                }
                if (chosenSpawn.Role != TeamMemberSpawn.MemberRole.Support)
                {
                    selectedNonSupport = true;
                }

                chosenSpawns.Add(chosenSpawn.Spawn);
            }

            return(chosenSpawns);
        }
예제 #25
0
        public override void DrawOnMap(T map)
        {
            Loc caveSize = ProposeSize(((IGenContext)map).Rand);

            if (caveSize.X != Draw.Width || caveSize.Y != Draw.Height)
            {
                DrawMapDefault(map);
                return;
            }

            //place room in a space that fits
            List <Loc> freeTiles = new List <Loc>();
            Loc        caveStart = Draw.Start + new Loc(2, 1);

            for (int x = 0; x < caveSize.X - 4; x++)
            {
                for (int y = 0; y < caveSize.Y - 4; y++)
                {
                    map.SetTile(new Loc(caveStart.X + x, caveStart.Y + y), map.RoomTerrain.Copy());
                    freeTiles.Add(new Loc(caveStart.X + x, caveStart.Y + y));
                }
            }
            //place tile treasures
            List <EffectTile> tileTreasures = TileTreasures.GetSpawns(map);

            for (int ii = 0; ii < tileTreasures.Count; ii++)
            {
                int        randIndex = ((IGenContext)map).Rand.Next(freeTiles.Count);
                EffectTile tile      = new EffectTile(tileTreasures[ii]);
                map.PlaceItem(freeTiles[randIndex], tile);
                freeTiles.RemoveAt(randIndex);
            }
            //place item treasures
            List <MapItem> treasures = Treasures.GetSpawns(map);

            for (int ii = 0; ii < treasures.Count; ii++)
            {
                int     randIndex = ((IGenContext)map).Rand.Next(freeTiles.Count);
                MapItem item      = treasures[ii];
                map.PlaceItem(freeTiles[randIndex], item);
                freeTiles.RemoveAt(randIndex);
            }

            //open the passage to the treasure room
            Loc tunnel = new Loc(caveStart.X + (caveSize.X - 4) / 2, caveStart.Y + caveSize.Y - 4);

            map.SetTile(tunnel, map.RoomTerrain.Copy());

            //dig the room into the treasure room
            for (int xx = 0; xx < 3; xx++)
            {
                for (int yy = 0; yy < 2; yy++)
                {
                    map.SetTile(new Loc(tunnel.X - 1 + xx, tunnel.Y + 1 + yy), map.RoomTerrain.Copy());
                }
            }


            //place monsters and items
            MonsterTeam team    = new MonsterTeam();
            Character   newChar = GuardTypes.Pick(((IGenContext)map).Rand).Spawn(team, map);

            map.PlaceItems(new TeamSpawn(team, false), new Loc[1] {
                tunnel
            });


            //dig tunnels within this room to hook up to the incoming demands
            foreach (Dir4 dir in DirExt.VALID_DIR4)
            {
                if (dir == Dir4.Up)
                {//if approached from the top, it must be either left or right.  Dig to that side and then dig up.
                    List <IntRange> upReq = RoomSideReqs[dir];
                    bool            left  = false;
                    bool            right = false;
                    for (int ii = 0; ii < upReq.Count; ii++)
                    {
                        bool hasLeft  = upReq[ii].Contains(Draw.Start.X) && BorderToFulfill[Dir4.Up][0];
                        bool hasRight = upReq[ii].Contains(Draw.End.X - 1) && BorderToFulfill[Dir4.Up][Draw.Width - 1];
                        if (hasLeft && hasRight)
                        {
                            if (((IGenContext)map).Rand.Next(2) == 0)
                            {
                                left = true;
                            }
                            else
                            {
                                right = true;
                            }
                        }
                        else
                        {
                            left  |= hasLeft;
                            right |= hasRight;
                        }
                    }
                    if (left)
                    {
                        DigAtBorder(map, Dir4.Left, Draw.End.Y - 1);
                        DigAtBorder(map, Dir4.Up, Draw.Start.X);
                    }
                    if (right)
                    {
                        DigAtBorder(map, Dir4.Right, Draw.End.Y - 1);
                        DigAtBorder(map, Dir4.Up, Draw.End.X - 1);
                    }
                }
                else if (dir == Dir4.Down)
                {//if approached from bottom, do nothing; we already fulfill every possibility
                }
                else
                {//if approached from the sides, dig at the bottommost Y of the room, because that was the only tile allowed.
                    if (RoomSideReqs[dir].Count > 0)
                    {
                        DigAtBorder(map, dir, Draw.End.Y - 1);
                    }
                }
            }

            for (int x = 0; x < Draw.Width; x++)
            {
                for (int y = 0; y < Draw.Height - 1; y++)
                {
                    Loc checkLoc = new Loc(Draw.X + x, Draw.Y + y);
                    if (!map.GetTile(checkLoc).TileEquivalent(map.RoomTerrain))
                    {
                        map.SetTile(checkLoc, map.UnbreakableTerrain.Copy());
                    }
                }
            }


            SetRoomBorders(map);
        }
예제 #26
0
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            int gapLength  = Vertical ? floorPlan.GridHeight : floorPlan.GridWidth;
            int sideLength = Vertical ? floorPlan.GridWidth : floorPlan.GridHeight;

            if (gapLength < 3 || sideLength < 2)
            {
                CreateErrorPath(rand, floorPlan);
                return;
            }

            //add the body
            int chosenTier = FromCorners ? (rand.Next(2) * gapLength - 1) : rand.Next(1, gapLength - 1);

            RoomGen <T> roomGen = GiantHallGen.Pick(rand);

            if (roomGen == null)
            {
                roomGen = GenericRooms.Pick(rand);
            }
            floorPlan.AddRoom(new Rect(Vertical ? 0 : chosenTier, Vertical ? chosenTier : 0, Vertical ? sideLength : 1, Vertical ? 1 : sideLength), roomGen, this.LargeRoomComponents.Clone());

            GenContextDebug.DebugProgress("Center Room");

            //add the legs
            for (int ii = 0; ii < sideLength; ii++)
            {
                if (chosenTier > 0)
                {
                    if (rand.Next(100) < LegPercent)
                    {
                        int roomTier = rand.Next(0, chosenTier);
                        floorPlan.AddRoom(new Loc(Vertical ? ii : roomTier, Vertical ? roomTier : ii), GenericRooms.Pick(rand), this.RoomComponents.Clone());
                        for (int jj = roomTier; jj < chosenTier; jj++)
                        {
                            SafeAddHall(new LocRay4(new Loc(Vertical ? ii : jj, Vertical ? jj : ii), Vertical ? Dir4.Down : Dir4.Right),
                                        floorPlan, GenericHalls.Pick(rand), GetDefaultGen(), this.RoomComponents, this.HallComponents, true);
                        }

                        GenContextDebug.DebugProgress("Add Leg");

                        int hasRoom = -1;
                        for (int jj = ii - 1; jj >= 0; jj--)
                        {
                            if (floorPlan.GetRoomPlan(new Loc(Vertical ? jj : roomTier, Vertical ? roomTier : jj)) != null)
                            {
                                hasRoom = jj;
                                break;
                            }
                        }
                        if (ii > 0 && hasRoom > -1)
                        {
                            if (rand.Next(100) < ConnectPercent)
                            {
                                for (int jj = ii; jj > hasRoom; jj--)
                                {
                                    SafeAddHall(new LocRay4(new Loc(Vertical ? jj : roomTier, Vertical ? roomTier : jj), Vertical ? Dir4.Left : Dir4.Up),
                                                floorPlan, GenericHalls.Pick(rand), GetDefaultGen(), this.RoomComponents, this.HallComponents, true);

                                    GenContextDebug.DebugProgress("Connect Leg");
                                }
                            }
                        }
                    }
                }
                if (chosenTier < gapLength - 1)
                {
                    if (rand.Next(100) < LegPercent)
                    {
                        int roomTier = rand.Next(chosenTier + 1, gapLength);
                        floorPlan.AddRoom(new Loc(Vertical ? ii : roomTier, Vertical ? roomTier : ii), GenericRooms.Pick(rand), this.RoomComponents.Clone());
                        for (int jj = chosenTier; jj < roomTier; jj++)
                        {
                            SafeAddHall(new LocRay4(new Loc(Vertical ? ii : jj, Vertical ? jj : ii), Vertical ? Dir4.Down : Dir4.Right),
                                        floorPlan, GenericHalls.Pick(rand), GetDefaultGen(), this.RoomComponents, this.HallComponents, true);
                        }

                        GenContextDebug.DebugProgress("Add Leg");

                        int hasRoom = -1;
                        for (int jj = ii - 1; jj >= 0; jj--)
                        {
                            if (floorPlan.GetRoomPlan(new Loc(Vertical ? jj : roomTier, Vertical ? roomTier : jj)) != null)
                            {
                                hasRoom = jj;
                                break;
                            }
                        }
                        if (ii > 0 && hasRoom > -1)
                        {
                            if (rand.Next(100) < ConnectPercent)
                            {
                                for (int jj = ii; jj > hasRoom; jj--)
                                {
                                    SafeAddHall(new LocRay4(new Loc(Vertical ? jj : roomTier, Vertical ? roomTier : jj), Vertical ? Dir4.Left : Dir4.Up),
                                                floorPlan, GenericHalls.Pick(rand), GetDefaultGen(), this.RoomComponents, this.HallComponents, true);

                                    GenContextDebug.DebugProgress("Connect Leg");
                                }
                            }
                        }
                    }
                }
            }
        }