public virtual void RegisterInGrid(ArchivedSegment what, SegmentStump where)
 {
     foreach (SegmentCell cell in what.Occupation[where.ZeroPosRot.Facing])
     {
         PlanningGrid[where.ZeroPosRot.U + cell.U, where.ZeroPosRot.R + cell.R] = GridOccupation.BlockedByCell;
     }
     foreach (SegmentCellOriented opening in what.Openings[where.ZeroPosRot.Facing])
     {
         PlanningGrid[where.ZeroPosRot.U + opening.U, where.ZeroPosRot.R + opening.R] = GridOccupation.BlockedByOpening;
     }
 }
 public static ArchivedSegment GetRandomSegment(int category, int theme, int doorType)
 {
     //Debug.Log("getting segment cat theme: " + category + " " + theme);
     if (category == SegmentCategory.Entrance)
     {
         return(Categoried [category, theme] [Random.Range(0, Categoried [category, theme].Count)]);
     }
     //if an entrance is needed, then pass random one. Otherwise try matching doors
     do
     {
         Result = Categoried [category, theme] [Random.Range(0, Categoried [category, theme].Count)];
     }while((Result.DoorsCombined & DoorType.GetCompatMaskForDoorType(doorType)) == 0);
     //at least one door in segment must be compatible with door exiting previous segment
     return(Result);
 }
    public int PathWeight;  //cells generated so far as branch from main path or cells generated so far as main path if part of it

    public void PlanFromScheme(ArchivedSegment scheme, SegmentStump gridStump)
    {
        Scheme     = scheme;
        ZeroPosRot = new SegmentCellOriented(gridStump.ZeroPosRot.U,
                                             gridStump.ZeroPosRot.R,
                                             gridStump.ZeroPosRot.Facing,
                                             gridStump.ZeroPosRot.Type,
                                             gridStump.ZeroPosRot.Altitude);
        SegmentRole = gridStump.StumpRole;
        PathDepth   = gridStump.PathDepth + 1;
        PathWeight  = gridStump.PathWeight + Scheme.Weight;

        this.HasParent(gridStump.Parent);
        if (gridStump.Parent != null)
        {
            gridStump.Parent.IsParentOf(this);
        }
    }
    public virtual bool CanItFit(ArchivedSegment what, SegmentStump whereTo)
    {
        int gridU, gridR;

        foreach (SegmentCell cell in what.Occupation[whereTo.ZeroPosRot.Facing])    //main cells intersection check
        {
            gridU = whereTo.ZeroPosRot.U + cell.U;
            gridR = whereTo.ZeroPosRot.R + cell.R;
            if ((gridU < 0) || (gridU > Settings.PlanGridDimensions) || (gridR < 0) || (gridR > Settings.PlanGridDimensions))
            {
                return(false);
            }

            if ((cell.U == 0) && (cell.R == 0))                                 //is it an entrance cell
            {
                if (PlanningGrid[gridU, gridR] == GridOccupation.BlockedByCell) //entrance can be planned on top of openings(that's the point)
                {
                    return(false);
                }
            }
            else
            {
                if (PlanningGrid[gridU, gridR] != GridOccupation.Empty) //not-entrance can be planned only on empty space
                {
                    return(false);
                }
            }
        }

        foreach (SegmentCellOriented opening in what.Openings[whereTo.ZeroPosRot.Facing])    //openings intersection check
        {
            gridU = whereTo.ZeroPosRot.U + opening.U;
            gridR = whereTo.ZeroPosRot.R + opening.R;
            if ((gridU < 0) || (gridU > Settings.PlanGridDimensions) || (gridR < 0) || (gridR > Settings.PlanGridDimensions))
            {
                return(false);
            }
            if (PlanningGrid[gridU, gridR] != GridOccupation.Empty) //opening for future segment needs at least 1 cell of open space
            {
                return(false);
            }
        }
        return(true);
    }
Пример #5
0
    public void FillRotations(ArchivedSegment segment) // fill in the 90 180 270 rotated variants of segment
    {
        //Pivot position and rotation (matters when segment is an ED variant and prefab pivot is displaced and has it's own rotation)
        segment.PivotCell[SegmentRotation.Right] = new SegmentCellOriented(-segment.PivotCell[SegmentRotation.Up].R,
                                                                           segment.PivotCell[SegmentRotation.Up].U,
                                                                           (segment.PivotCell[SegmentRotation.Up].Facing + 1) % 4,
                                                                           0,
                                                                           segment.PivotCell[SegmentRotation.Up].Altitude);
        segment.PivotCell[SegmentRotation.Down] = new SegmentCellOriented(-segment.PivotCell[SegmentRotation.Up].U,
                                                                          -segment.PivotCell[SegmentRotation.Up].R,
                                                                          (segment.PivotCell[SegmentRotation.Up].Facing + 2) % 4,
                                                                          0,
                                                                          segment.PivotCell[SegmentRotation.Up].Altitude);
        segment.PivotCell[SegmentRotation.Left] = new SegmentCellOriented(segment.PivotCell[SegmentRotation.Up].R,
                                                                          -segment.PivotCell[SegmentRotation.Up].U,
                                                                          (segment.PivotCell[SegmentRotation.Up].Facing + 3) % 4,
                                                                          0,
                                                                          segment.PivotCell[SegmentRotation.Up].Altitude);

        segment.Occupation[SegmentRotation.Right] = new List <SegmentCell>();
        segment.Occupation[SegmentRotation.Down]  = new List <SegmentCell>();
        segment.Occupation[SegmentRotation.Left]  = new List <SegmentCell>();
        foreach (SegmentCell cell in segment.Occupation[SegmentRotation.Up])
        {
            segment.Occupation[SegmentRotation.Right].Add(new SegmentCell(-cell.R, cell.U));
            segment.Occupation[SegmentRotation.Down].Add(new SegmentCell(-cell.U, -cell.R));
            segment.Occupation[SegmentRotation.Left].Add(new SegmentCell(cell.R, -cell.U));
        }

        segment.Openings[SegmentRotation.Right] = new List <SegmentCellOriented>();
        segment.Openings[SegmentRotation.Down]  = new List <SegmentCellOriented>();
        segment.Openings[SegmentRotation.Left]  = new List <SegmentCellOriented>();
        foreach (SegmentCellOriented opening in segment.Openings[SegmentRotation.Up])
        {
            segment.Openings[SegmentRotation.Right].Add(new SegmentCellOriented(-opening.R, opening.U, (opening.Facing + 1) % 4, opening.Type, opening.Altitude));
            segment.Openings[SegmentRotation.Down].Add(new SegmentCellOriented(-opening.U, -opening.R, (opening.Facing + 2) % 4, opening.Type, opening.Altitude));
            segment.Openings[SegmentRotation.Left].Add(new SegmentCellOriented(opening.R, -opening.U, (opening.Facing + 3) % 4, opening.Type, opening.Altitude));
        }
    }
    //private int SideBranchingEntropy = 0;   //influences chances of sideways branching; rises as branches fail to branch when they should (dungeon topology wont allow it)
    //WIP
    public override bool GeneratePlan(out DungeonPlan dungeonPlan)
    {
        dungeonPlan = new DungeonPlan();
        SegmentStump        MainPathStump;
        List <SegmentStump> SidewayStumps = new List <SegmentStump>();

        if (PlanningGrid == null)
        {
            PlanningGrid = new byte[Settings.PlanGridDimensions + 1, Settings.PlanGridDimensions + 1];
        }
        else
        {
            Array.Clear(PlanningGrid, 0, PlanningGrid.Length);
        }


        //ENTRANCE
        PlannedSegment EntrancePlan  = new PlannedSegment();
        SegmentStump   EntranceStump = new SegmentStump(null,
                                                        new SegmentCellOriented((int)(Settings.PlanGridDimensions * EntranceMargin.x),
                                                                                (int)(Settings.PlanGridDimensions * EntranceMargin.y),
                                                                                SegmentRotation.Up,
                                                                                DoorType.NonExistant, //no door into first segment
                                                                                0),                   //starting altitude is considered zero
                                                        DungeonSegmentRole.MainPath,                  //Entrance is a start of main path
                                                        0,                                            //dungeon starting segment has 0 depth and weight before it
                                                        0);
        ArchivedSegment schemeChoice = TryFindFittingSegment(SegmentCategory.Entrance, EntranceStump);

        if (schemeChoice == null)
        {
            Debug.Log("Could not plan entrance");
            return(false);
        }
        else
        {
            RegisterInGrid(schemeChoice, EntranceStump);
        }
        EntrancePlan.PlanFromScheme(schemeChoice, EntranceStump);
        dungeonPlan.AddSegment(EntrancePlan);
        List <SegmentStump> OpeningsStumps = SegmentStump.MakeStumpsForOpenings(EntrancePlan);

        ShuffleList <SegmentStump>(OpeningsStumps);

        MainPathStump           = OpeningsStumps[0]; //first one after shuffle is main, the rest are sideways
        MainPathStump.StumpRole = DungeonSegmentRole.MainPath;
        OpeningsStumps.RemoveAt(0);
        foreach (SegmentStump stump in OpeningsStumps)
        {
            stump.StumpRole  = DungeonSegmentRole.Sideway;
            stump.PathDepth  = 0;   //depth and weight are related to sideway now
            stump.PathWeight = 0;
            SidewayStumps.Add(stump);
        }


        //MAIN PATH
        PlannedSegment MainPathPlan;
        int            ChosenCategory;

        while ((ChosenCategory = ChooseCategoryForStump(MainPathStump)) != SegmentCategory.Exit)
        {
            MainPathPlan = new PlannedSegment();
            schemeChoice = TryFindFittingSegment(ChosenCategory, MainPathStump);
            if (schemeChoice == null)
            {
                //Debug.Log("Could not plan part of main path at Depth / Weight: " + MainPathStump.PathDepth + " / " + MainPathStump.PathWeight);
                return(false);
            }
            else
            {
                RegisterInGrid(schemeChoice, MainPathStump);
            }
            MainPathPlan.PlanFromScheme(schemeChoice, MainPathStump);
            dungeonPlan.AddSegment(MainPathPlan);
            OpeningsStumps = SegmentStump.MakeStumpsForOpenings(MainPathPlan);
            ShuffleList <SegmentStump>(OpeningsStumps);

            MainPathStump           = OpeningsStumps[0]; //first one after shuffle is main, the rest are sideways
            MainPathStump.StumpRole = DungeonSegmentRole.MainPath;
            OpeningsStumps.RemoveAt(0);
            foreach (SegmentStump stump in OpeningsStumps)
            {
                stump.StumpRole  = DungeonSegmentRole.Sideway;
                stump.PathDepth  = 0;
                stump.PathWeight = 0;
                SidewayStumps.Add(stump);
            }
        }


        //EXIT
        PlannedSegment MainPathExitPlan = new PlannedSegment();

        schemeChoice = TryFindFittingSegment(SegmentCategory.Exit, MainPathStump);
        if (schemeChoice == null)
        {
            //Debug.Log("Could not plan exit part of main path");
            return(false);
        }
        else
        {
            RegisterInGrid(schemeChoice, MainPathStump);
        }
        MainPathExitPlan.PlanFromScheme(schemeChoice, MainPathStump);
        dungeonPlan.AddSegment(MainPathExitPlan);


        //SIDEWAYS
        PlannedSegment SidewayPlan;

        while (SidewayStumps.Count != 0)
        {
            ChosenCategory = ChooseCategoryForStump(SidewayStumps[0]);
            SidewayPlan    = new PlannedSegment();
            schemeChoice   = TryFindFittingSegment(ChosenCategory, SidewayStumps[0]);
            if (schemeChoice == null)
            {
                //Debug.Log("Could not plan a sideway");
                return(false);
            }
            else
            {
                RegisterInGrid(schemeChoice, SidewayStumps[0]);
            }
            SidewayPlan.PlanFromScheme(schemeChoice, SidewayStumps[0]);
            dungeonPlan.AddSegment(SidewayPlan);

            OpeningsStumps = SegmentStump.MakeStumpsForOpenings(SidewayPlan); //if sideway continues - add its exit stumps to the end of SidewayStumps
            foreach (SegmentStump stump in OpeningsStumps)
            {
                stump.StumpRole = DungeonSegmentRole.Sideway;
                SidewayStumps.Add(stump);
            }
            SidewayStumps.RemoveAt(0); //stump is built upon and should be removed
        }

        return(true); //generated successfully
    }
Пример #7
0
    public void Variate()                                                                        //make entrance-displaced variants and fill in their rotations
    {
        if ((Openings[SegmentRotation.Up].Count != 0) && (Category != SegmentCategory.Entrance)) //entrance can not have alternative way to enter in it
        {
            List <SegmentCell>         NewOccupation;
            List <SegmentCellOriented> NewOpenings;
            int NeededSegmentRotation = 0;
            int UCorrection           = 0;
            int RCorrection           = 0;
            foreach (SegmentCellOriented opening in Openings[SegmentRotation.Up])
            {
                NewOccupation = new List <SegmentCell>();
                NewOpenings   = new List <SegmentCellOriented>();
                switch (opening.Facing)
                {
                case CellFacing.Up:
                    NeededSegmentRotation = SegmentRotation.Down; //rotation of the original that will be a default(up) rotation for variant
                    UCorrection           = opening.U - 1;        //movement of the segment after rotation that is needed for the cell with opening(new entrance) to be at local 0.0
                    RCorrection           = opening.R;
                    break;

                case CellFacing.Right:
                    NeededSegmentRotation = SegmentRotation.Right;
                    UCorrection           = opening.R - 1;
                    RCorrection           = -opening.U;
                    break;

                case CellFacing.Down:
                    NeededSegmentRotation = SegmentRotation.Up;
                    UCorrection           = -opening.U - 1;
                    RCorrection           = -opening.R;
                    break;

                case CellFacing.Left:
                    NeededSegmentRotation = SegmentRotation.Left;
                    UCorrection           = -opening.R - 1;
                    RCorrection           = opening.U;
                    break;
                }

                foreach (SegmentCell rotcell in Occupation[NeededSegmentRotation])
                {
                    NewOccupation.Add(new SegmentCell(rotcell.U + UCorrection, rotcell.R + RCorrection));
                }

                foreach (SegmentCellOriented rotopening in Openings[NeededSegmentRotation])
                {
                    if ((rotopening.U + UCorrection == -1) && (rotopening.R + RCorrection == 0) && (rotopening.Facing == CellFacing.Down))  //check and skip if exit with current opening is the new entrance
                    {
                        continue;
                    }
                    NewOpenings.Add(new SegmentCellOriented(rotopening.U + UCorrection, rotopening.R + RCorrection, rotopening.Facing, rotopening.Type, rotopening.Altitude - opening.Altitude));
                }

                int OldEntranceOpeningU      = 0; //Old entrance should be listed as viable opening now
                int OldEntranceOpeningR      = 0;
                int OldEntranceOpeningFacing = 0;
                switch (NeededSegmentRotation)
                {
                case SegmentRotation.Up:
                    OldEntranceOpeningU      = UCorrection - 1;
                    OldEntranceOpeningR      = RCorrection;
                    OldEntranceOpeningFacing = CellFacing.Down;
                    break;

                case SegmentRotation.Right:
                    OldEntranceOpeningU      = UCorrection;
                    OldEntranceOpeningR      = RCorrection - 1;
                    OldEntranceOpeningFacing = CellFacing.Left;
                    break;

                case SegmentRotation.Down:
                    OldEntranceOpeningU      = UCorrection + 1;
                    OldEntranceOpeningR      = RCorrection;
                    OldEntranceOpeningFacing = CellFacing.Up;
                    break;

                case SegmentRotation.Left:
                    OldEntranceOpeningU      = UCorrection;
                    OldEntranceOpeningR      = RCorrection + 1;
                    OldEntranceOpeningFacing = CellFacing.Right;
                    break;
                }
                NewOpenings.Add(new SegmentCellOriented(OldEntranceOpeningU, OldEntranceOpeningR, OldEntranceOpeningFacing, EntranceDoorType, -opening.Altitude));     //add an old entrance as possible exit with opening

                ArchivedSegment Variant = new ArchivedSegment(NewOccupation,
                                                              NewOpenings,
                                                              opening.Type,
                                                              Theme,
                                                              Category,
                                                              PrefabName,
                                                              Chance,
                                                              false);
                //pivot of the prefab is displaced and has added rotation
                Variant.PivotCell[SegmentRotation.Up] = new SegmentCellOriented(UCorrection, RCorrection, NeededSegmentRotation, DoorType.NonExistant, -opening.Altitude);
                FillRotations(Variant);
                EDVariants.Add(Variant);
            }
        }
    }