예제 #1
0
        protected virtual void GatherTilesToInject()
        {
            Random injectionRandomStream = new Random(ChosenSeed);

            // Gather from DungeonFlow
            foreach (var rule in DungeonFlow.TileInjectionRules)
            {
                // Ignore invalid rules
                if (rule.TileSet == null || (!rule.CanAppearOnMainPath && !rule.CanAppearOnBranchPath))
                {
                    continue;
                }

                bool isOnMainPath = (!rule.CanAppearOnBranchPath) ? true : (!rule.CanAppearOnMainPath) ? false : injectionRandomStream.NextDouble() > 0.5;

                InjectedTile injectedTile = new InjectedTile(rule.TileSet,
                                                             isOnMainPath,
                                                             rule.NormalizedPathDepth.GetRandom(injectionRandomStream),
                                                             rule.NormalizedBranchDepth.GetRandom(injectionRandomStream),
                                                             rule.IsRequired);

                tilesPendingInjection.Add(injectedTile);
            }

            // Gather from external delegates
            if (TileInjectionMethods != null)
            {
                TileInjectionMethods(injectionRandomStream, ref tilesPendingInjection);
            }
        }
예제 #2
0
        protected virtual Tile AddTile(Tile attachTo, IEnumerable <TileSet> useableTileSets, float normalizedDepth, DungeonArchetype archetype, TilePlacementResult result = TilePlacementResult.None)
        {
            bool isOnMainPath = (Status == GenerationStatus.MainPath);
            bool isFirstTile  = attachTo == null;

            // Check list of tiles to inject
            InjectedTile chosenInjectedTile        = null;
            int          injectedTileIndexToRemove = -1;

            bool isPlacingSpecificRoom = isOnMainPath && (archetype == null);

            if (tilesPendingInjection != null && !isPlacingSpecificRoom)
            {
                float pathDepth   = (isOnMainPath) ? normalizedDepth : attachTo.Placement.PathDepth / (float)(targetLength - 1);
                float branchDepth = (isOnMainPath) ? 0 : normalizedDepth;

                for (int i = 0; i < tilesPendingInjection.Count; i++)
                {
                    var injectedTile = tilesPendingInjection[i];

                    if (injectedTile.ShouldInjectTileAtPoint(isOnMainPath, pathDepth, branchDepth))
                    {
                        chosenInjectedTile        = injectedTile;
                        injectedTileIndexToRemove = i;

                        break;
                    }
                }
            }


            // Select appropriate tile weights
            IEnumerable <GameObjectChance> chanceEntries;

            if (chosenInjectedTile != null)
            {
                chanceEntries = new List <GameObjectChance>(chosenInjectedTile.TileSet.TileWeights.Weights);
            }
            else
            {
                chanceEntries = useableTileSets.SelectMany(x => x.TileWeights.Weights);
            }


            // Apply constraint overrides
            bool allowRepeatTile = (isFirstTile) ? true : attachTo.AllowImmediateRepeats;

            if (OverrideAllowImmediateRepeats)
            {
                allowRepeatTile = AllowImmediateRepeats;
            }

            bool allowRotation = (isFirstTile) ? false : attachTo.AllowRotation;

            if (OverrideAllowTileRotation)
            {
                allowRotation = AllowTileRotation;
            }



            DoorwayPairFinder doorwayPairFinder = new DoorwayPairFinder()
            {
                RandomStream            = RandomStream,
                Archetype               = archetype,
                GetTileTemplateDelegate = GetTileTemplate,
                IsOnMainPath            = isOnMainPath,
                NormalizedDepth         = normalizedDepth,
                PreviousTile            = attachTo,
                PreviousPrefab          = (attachTo == null) ? null : placedTilePrefabs[attachTo],
                UpVector      = UpVector,
                AllowRotation = allowRotation,
                TileWeights   = new List <GameObjectChance>(chanceEntries),

                IsTileAllowedPredicate = (Tile previousTile, GameObject previousPrefab, GameObject prefab, ref float weight) =>
                {
                    bool isRepeat = (prefab == previousPrefab);

                    return(!isRepeat || allowRepeatTile);
                },
            };

            int?maxPairingAttempts             = (UseMaximumPairingAttempts) ? (int?)MaxPairingAttempts : null;
            Queue <DoorwayPair> pairsToTest    = doorwayPairFinder.GetDoorwayPairs(maxPairingAttempts);
            TilePlacementResult lastTileResult = TilePlacementResult.NoValidTile;
            Tile createdTile = null;

            while (pairsToTest.Count > 0)
            {
                var pair = pairsToTest.Dequeue();

                lastTileResult = TryPlaceTile(pair, archetype, out createdTile);

                if (lastTileResult == TilePlacementResult.None)
                {
                    break;
                }
                else
                {
                    AddTilePlacementResult(lastTileResult);
                }
            }

            // Successfully placed the tile
            if (lastTileResult == TilePlacementResult.None)
            {
                // We've successfully injected the tile, so we can remove it from the pending list now
                if (chosenInjectedTile != null)
                {
                    injectedTiles[createdTile] = chosenInjectedTile;
                    tilesPendingInjection.RemoveAt(injectedTileIndexToRemove);

                    if (isOnMainPath)
                    {
                        targetLength++;
                    }
                }

                return(createdTile);
            }
            else
            {
                return(null);
            }
        }