Exemple #1
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;
                        }
                    }
                }
            }
        }
Exemple #2
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);
        }
Exemple #3
0
        public void GetWallDir(int gridType, Dir4 result)
        {
            // no correct grounds
            string[] inGrid =
            {
                "XXX",
                "XXX",
                "XXX",
            };

            switch (gridType)
            {
                case 1:
                    // one correct ground, all valid block
                    inGrid = new string[]
                    {
                        "XXX",
                        "XXX",
                        "X.X",
                    };
                    break;
                case 2:
                    inGrid = new string[]
                    {
                        "XXX",
                        ".XX",
                        "XXX",
                    };
                    break;
                case 3:
                    // multiple correct ground
                    inGrid = new string[]
                    {
                        "XXX",
                        ".XX",
                        "X.X",
                    };
                    break;
                case 4:
                    // one correct ground, but one invalid
                    inGrid = new string[]
                    {
                        "XXX",
                        "~XX",
                        "X.X",
                    };
                    break;
                case 5:
                    // one correct ground, one crucial diagonal an invalid block
                    inGrid = new string[]
                    {
                        "XX~",
                        "XXX",
                        "X.X",
                    };
                    break;
                case 6:
                    // one correct ground, both noncrucial diagonal an invalid block
                    inGrid = new string[]
                    {
                        "XXX",
                        "XXX",
                        "~.~",
                    };
                    break;
                default:
                    break;
            }

            char[][] map = GridTest.InitGrid(inGrid);

            bool CheckBlock(Loc testLoc) => map[testLoc.X][testLoc.Y] == 'X';
            bool CheckGround(Loc testLoc) => map[testLoc.X][testLoc.Y] == '.';

            LocRay4 locRay = Detection.GetWallDir(new Loc(1), CheckBlock, CheckGround);
            Assert.That(locRay, Is.EqualTo(new LocRay4(new Loc(1), result)));
        }