/// <summary>
        /// Gets a basic layout generator that should not be used to generated layouts with corridors.
        /// </summary>
        /// <typeparam name="TNode"></typeparam>
        /// <returns></returns>
        public static ChainBasedGenerator <MapDescription <TNode>, Layout <Configuration <EnergyData>, BasicEnergyData>, int, Configuration <EnergyData>, IMapLayout <TNode> > GetDefaultChainBasedGenerator <TNode>()
        {
            var layoutGenerator = new ChainBasedGenerator <MapDescription <TNode>, Layout <Configuration <EnergyData>, BasicEnergyData>, int, Configuration <EnergyData>, IMapLayout <TNode> >();

            var chainDecomposition           = new BreadthFirstChainDecomposition <int>(new GraphDecomposer <int>());
            var configurationSpacesGenerator = new ConfigurationSpacesGenerator(new PolygonOverlap(), DoorHandler.DefaultHandler, new OrthogonalLineIntersection(), new GridPolygonUtils());
            var generatorPlanner             = new BasicGeneratorPlanner <Layout <Configuration <EnergyData>, BasicEnergyData> >();

            layoutGenerator.SetChainDecompositionCreator(mapDescription => chainDecomposition);
            layoutGenerator.SetConfigurationSpacesCreator(mapDescription => configurationSpacesGenerator.Generate <TNode, Configuration <EnergyData> >(mapDescription));
            layoutGenerator.SetInitialLayoutCreator(mapDescription => new Layout <Configuration <EnergyData>, BasicEnergyData>(mapDescription.GetGraph()));
            layoutGenerator.SetGeneratorPlannerCreator(mapDescription => generatorPlanner);
            layoutGenerator.SetLayoutConverterCreator((mapDescription, configurationSpaces) => new BasicLayoutConverter <Layout <Configuration <EnergyData>, BasicEnergyData>, TNode, Configuration <EnergyData> >(mapDescription, configurationSpaces, configurationSpacesGenerator.LastIntAliasMapping));
            layoutGenerator.SetLayoutEvolverCreator((mapDescription, layoutOperations) => new SimulatedAnnealingEvolver <Layout <Configuration <EnergyData>, BasicEnergyData>, int, Configuration <EnergyData> >(layoutOperations));
            layoutGenerator.SetLayoutOperationsCreator((mapDescription, configurationSpaces) =>
            {
                var layoutOperations = new LayoutOperationsWithConstraints <Layout <Configuration <EnergyData>, BasicEnergyData>, int, Configuration <EnergyData>, IntAlias <GridPolygon>, EnergyData, BasicEnergyData>(configurationSpaces, configurationSpaces.GetAverageSize());

                var averageSize = configurationSpaces.GetAverageSize();

                layoutOperations.AddNodeConstraint(new BasicContraint <Layout <Configuration <EnergyData>, BasicEnergyData>, int, Configuration <EnergyData>, EnergyData, IntAlias <GridPolygon> >(
                                                       new FastPolygonOverlap(),
                                                       averageSize,
                                                       configurationSpaces
                                                       ));

                return(layoutOperations);
            });

            return(layoutGenerator);
        }
Ejemplo n.º 2
0
 public void SetUp()
 {
     configurationSpacesGenerator = new ConfigurationSpacesGenerator(
         new PolygonOverlap(),
         DoorHandler.DefaultHandler,
         new OrthogonalLineIntersection(),
         new GridPolygonUtils());
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Gets a generator that can work with corridors.
        /// </summary>
        /// <remarks>
        /// TODO: This is only a temporary solution because we must be able to inject our own corridor nodes creator and this is the easiest way right now.
        /// </remarks>
        /// <param name="offsets"></param>
        /// <param name="canTouch">Whether rooms can touch. Perfomance is decreased when set to false.</param>
        /// <param name="corridorNodesCreator"></param>
        /// <returns></returns>
        public static ChainBasedGenerator <MapDescription <TNode>, Layout <Configuration <CorridorsData>, BasicEnergyData>, int, Configuration <CorridorsData>, IMapLayout <TNode> > GetChainBasedGeneratorWithCorridors <TNode>(List <int> offsets, bool canTouch = false, ICorridorNodesCreator <TNode> corridorNodesCreator = null)
        {
            var layoutGenerator = new ChainBasedGenerator <MapDescription <TNode>, Layout <Configuration <CorridorsData>, BasicEnergyData>, int, Configuration <CorridorsData>, IMapLayout <TNode> >();

            var chainDecomposition           = new BreadthFirstChainDecomposition <int>();
            var configurationSpacesGenerator = new ConfigurationSpacesGenerator(new PolygonOverlap(), DoorHandler.DefaultHandler, new OrthogonalLineIntersection(), new GridPolygonUtils());
            var generatorPlanner             = new BasicGeneratorPlanner <Layout <Configuration <CorridorsData>, BasicEnergyData> >();

            layoutGenerator.SetChainDecompositionCreator(mapDescription => new CorridorsChainDecomposition <int>(mapDescription, chainDecomposition));
            layoutGenerator.SetConfigurationSpacesCreator(mapDescription => configurationSpacesGenerator.Generate <TNode, Configuration <CorridorsData> >(mapDescription));
            layoutGenerator.SetInitialLayoutCreator(mapDescription => new Layout <Configuration <CorridorsData>, BasicEnergyData>(mapDescription.GetGraph()));
            layoutGenerator.SetGeneratorPlannerCreator(mapDescription => generatorPlanner);
            layoutGenerator.SetLayoutConverterCreator((mapDescription, configurationSpaces) => new BasicLayoutConverter <Layout <Configuration <CorridorsData>, BasicEnergyData>, TNode, Configuration <CorridorsData> >(mapDescription, configurationSpaces, configurationSpacesGenerator.LastIntAliasMapping, corridorNodesCreator));
            layoutGenerator.SetLayoutEvolverCreator((mapDescription, layoutOperations) => new SimulatedAnnealingEvolver <Layout <Configuration <CorridorsData>, BasicEnergyData>, int, Configuration <CorridorsData> >(layoutOperations));
            layoutGenerator.SetLayoutOperationsCreator((mapDescription, configurationSpaces) =>
            {
                var corridorConfigurationSpaces = configurationSpacesGenerator.Generate <TNode, Configuration <CorridorsData> >(mapDescription, offsets);
                var layoutOperations            = new LayoutOperationsWithCorridors <Layout <Configuration <CorridorsData>, BasicEnergyData>, int, Configuration <CorridorsData>, IntAlias <GridPolygon>, CorridorsData, BasicEnergyData>(configurationSpaces, mapDescription, corridorConfigurationSpaces, configurationSpaces.GetAverageSize());
                var polygonOverlap = new FastPolygonOverlap();

                var averageSize = configurationSpaces.GetAverageSize();

                layoutOperations.AddNodeConstraint(new BasicContraint <Layout <Configuration <CorridorsData>, BasicEnergyData>, int, Configuration <CorridorsData>, CorridorsData, IntAlias <GridPolygon> >(
                                                       polygonOverlap,
                                                       averageSize,
                                                       configurationSpaces
                                                       ));

                layoutOperations.AddNodeConstraint(new CorridorConstraints <Layout <Configuration <CorridorsData>, BasicEnergyData>, int, Configuration <CorridorsData>, CorridorsData, IntAlias <GridPolygon> >(
                                                       mapDescription,
                                                       averageSize,
                                                       corridorConfigurationSpaces
                                                       ));

                if (!canTouch)
                {
                    layoutOperations.AddNodeConstraint(new TouchingConstraints <Layout <Configuration <CorridorsData>, BasicEnergyData>, int, Configuration <CorridorsData>, CorridorsData, IntAlias <GridPolygon> >(
                                                           mapDescription,
                                                           polygonOverlap
                                                           ));
                }

                return(layoutOperations);
            });

            return(layoutGenerator);
        }
        private void SetupGenerator()
        {
            var mapping       = mapDescription.GetMapping();
            var chainsGeneric = configuration.Chains;

            if (chainsGeneric == null)
            {
                var chainDecomposition = new TwoStageChainDecomposition <TNode>(mapDescriptionOriginal, new BreadthFirstChainDecomposition <TNode>(configuration.ChainDecompositionConfiguration ?? new ChainDecompositionConfiguration()));
                chainsGeneric = chainDecomposition.GetChains(mapDescriptionOriginal.GetGraph());
            }

            var chains = chainsGeneric
                         .Select(x => new Chain <int>(x.Nodes.Select(y => mapping[y]).ToList(), x.Number))
                         .ToList();

            var generatorPlanner = new GeneratorPlanner <Layout <Configuration <CorridorsData> >, int>(configuration.SimulatedAnnealingMaxBranching);

            var configurationSpacesGenerator = new ConfigurationSpacesGenerator(
                new PolygonOverlap(),
                DoorHandler.DefaultHandler,
                new OrthogonalLineIntersection(),
                new GridPolygonUtils());
            var configurationSpaces = configurationSpacesGenerator.GetConfigurationSpaces <Configuration <CorridorsData> >(mapDescription);

            //var corridorConfigurationSpaces = mapDescription.IsWithCorridors ? configurationSpacesGenerator.Generate<TNode, Configuration<CorridorsData>>(mapDescription, mapDescription.CorridorsOffsets) : configurationSpaces;
            var corridorConfigurationSpaces = configurationSpaces;

            var averageSize    = configurationSpaces.GetAverageSize();
            var polygonOverlap = new FastPolygonOverlap();

            var stageOneConstraints =
                new List <INodeConstraint <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>,
                                           CorridorsData> >
            {
                new BasicConstraint <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>,
                                     CorridorsData, IntAlias <PolygonGrid2D> >(
                    new FastPolygonOverlap(),
                    averageSize,
                    configurationSpaces
                    ),
                new CorridorConstraints <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>, CorridorsData, IntAlias <PolygonGrid2D> >(
                    mapDescription,
                    averageSize,
                    corridorConfigurationSpaces
                    ),
            };

            if (!configuration.RoomsCanTouch)
            {
                stageOneConstraints.Add(new TouchingConstraints <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>, CorridorsData, IntAlias <PolygonGrid2D> >(
                                            mapDescription,
                                            polygonOverlap
                                            ));
            }

            var stageOneConstraintsEvaluator = new ConstraintsEvaluator <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>, IntAlias <PolygonGrid2D>, CorridorsData>(stageOneConstraints);

            //if (mapDescription.IsWithCorridors)
            //{
            //    layoutOperations.AddNodeConstraint(new CorridorConstraints<Layout<Configuration<CorridorsData>>, int, Configuration<CorridorsData>, CorridorsData, IntAlias<GridPolygon>>(
            //        mapDescription,
            //        averageSize,
            //        corridorConfigurationSpaces
            //    ));

            //    if (!false) // TODO:
            //    {
            //        var polygonOverlap = new FastPolygonOverlap();
            //        layoutOperations.AddNodeConstraint(new TouchingConstraints<Layout<Configuration<CorridorsData>>, int, Configuration<CorridorsData>, CorridorsData, IntAlias<GridPolygon>>(
            //            mapDescription,
            //            polygonOverlap
            //        ));
            //    }
            //}


            var roomShapesHandler = new RoomShapesHandler <int, Configuration <CorridorsData> >(
                configurationSpaces,
                configurationSpaces.GetIntAliasMapping(),
                mapDescription,
                configuration.RepeatModeOverride
                );

            var layoutOperations = new LayoutOperations <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>, IntAlias <PolygonGrid2D>, CorridorsData>(corridorConfigurationSpaces, configurationSpaces.GetAverageSize(), mapDescription, stageOneConstraintsEvaluator, stageOneConstraintsEvaluator, roomShapesHandler, configuration.ThrowIfRepeatModeNotSatisfied);

            var initialLayout   = new Layout <Configuration <CorridorsData> >(mapDescription.GetGraph());
            var layoutConverter =
                new BasicLayoutConverter <Layout <Configuration <CorridorsData> >, TNode,
                                          Configuration <CorridorsData> >(mapDescription, configurationSpaces,
                                                                          configurationSpaces.GetIntAliasMapping());

            var layoutEvolver =
                new PlatformersEvolver <Layout <Configuration <CorridorsData> >, int,
                                        Configuration <CorridorsData> >(layoutOperations);

            generator = new ChainBasedGenerator <Layout <Configuration <CorridorsData> >, MapLayout <TNode>, int>(initialLayout, generatorPlanner, chains, layoutEvolver, layoutConverter);

            generator.OnRandomInjected += (random) =>
            {
                ((IRandomInjectable)configurationSpaces).InjectRandomGenerator(random);
                ((IRandomInjectable)layoutOperations).InjectRandomGenerator(random);
                ((IRandomInjectable)layoutEvolver).InjectRandomGenerator(random);
                ((IRandomInjectable)layoutConverter).InjectRandomGenerator(random);
            };

            generator.OnCancellationTokenInjected += (token) =>
            {
                ((ICancellable)generatorPlanner).SetCancellationToken(token);
                ((ICancellable)layoutEvolver).SetCancellationToken(token);
            };

            // layoutEvolver.OnEvent += (sender, args) => OnSimulatedAnnealingEvent?.Invoke(sender, args);
            layoutEvolver.OnPerturbed          += (sender, layout) => OnPerturbed?.Invoke(layoutConverter.Convert(layout, false));
            layoutEvolver.OnPerturbed          += (sender, layout) => OnPerturbedInternal?.Invoke(layout);
            layoutEvolver.OnValid              += (sender, layout) => OnPartialValid?.Invoke(layoutConverter.Convert(layout, true));
            generatorPlanner.OnLayoutGenerated += layout => OnValid?.Invoke(layoutConverter.Convert(layout, true));
        }