示例#1
0
 public Configuration(IntAlias <PolygonGrid2D> shape, Vector2Int position, TEnergyData energyData, int node)
 {
     ShapeContainer = shape;
     Position       = position;
     EnergyData     = energyData;
     Node           = node;
 }
            public WeightedShape(IntAlias <GridPolygon> shape, double weight)
            {
                if (weight <= 0)
                {
                    throw new ArgumentException("Weight must be greater than zero", nameof(weight));
                }

                Shape  = shape;
                Weight = weight;
            }
        private IntAlias <PolygonGrid2D> GetRoomTemplateInstanceAlias(RoomTemplateInstance roomTemplateInstance)
        {
            if (IntAliasMapping.TryGetValue(roomTemplateInstance, out var alias))
            {
                return(alias);
            }

            var newAlias = new IntAlias <PolygonGrid2D>(IntAliasMapping.Count, roomTemplateInstance.RoomShape);

            IntAliasMapping.Add(roomTemplateInstance, newAlias);

            return(newAlias);
        }
        protected override List <GridRectangle> GetDecomposition(IntAlias <GridPolygon> polygon)
        {
            var alias = polygon.Alias;

            if (alias >= decompositions.Count)
            {
                while (alias >= decompositions.Count)
                {
                    decompositions.Add(null);
                }
            }

            var decomposition = decompositions[alias];

            if (decomposition == null)
            {
                decomposition         = polygonPartitioning.GetPartitions(polygon.Value);
                decompositions[alias] = decomposition;
            }

            return(decomposition);
        }
 private void SetConfiguration(Layout <Configuration <CorridorsData> > layout, int node, IntAlias <PolygonGrid2D> alias)
 {
     layout.SetConfiguration(node, new Configuration <CorridorsData>(alias, new Vector2Int(0, 0), new CorridorsData(), node));
 }
示例#6
0
 public static Area Seek(int area)
 {
     return((Area)IntAlias.Seek(CacheIndex.Area, area));
 }
示例#7
0
 public static Hall Seek(int hall)
 {
     return((Hall)IntAlias.Seek(CacheIndex.Hall, hall));
 }
 protected override GridRectangle GetBoundingRectangle(IntAlias <GridPolygon> polygon)
 {
     return(polygon.Value.BoundingRectangle);
 }
 protected override RectangleGrid2D GetBoundingRectangle(IntAlias <PolygonGrid2D> polygon)
 {
     return(polygon.Value.BoundingRectangle);
 }
示例#10
0
 protected bool Equals(IntAlias <T> other)
 {
     return(Alias == other.Alias);
 }
        /// <summary>
        /// Computes configuration spaces for a given map description.
        /// </summary>
        /// <typeparam name="TNode"></typeparam>
        /// <typeparam name="TConfiguration"></typeparam>
        /// <param name="mapDescription"></param>
        /// <param name="offsets"></param>
        /// <returns></returns>
        public IConfigurationSpaces <int, IntAlias <GridPolygon>, TConfiguration, ConfigurationSpace> Generate <TNode, TConfiguration>(MapDescription <TNode> mapDescription, List <int> offsets = null)
            where TConfiguration : IConfiguration <IntAlias <GridPolygon> >
        {
            if (offsets != null && offsets.Count == 0)
            {
                throw new ArgumentException("There must be at least one offset if they are set", nameof(offsets));
            }

            if (mapDescription.IsWithCorridors && mapDescription.GetCorridorShapes().Count == 0)
            {
                throw new ArgumentException("The map description has corridors enabled but there are no shapes for them.", nameof(mapDescription));
            }

            var graph                  = mapDescription.GetGraph();
            var aliasCounter           = 0;
            var allShapes              = new Dictionary <int, Tuple <IntAlias <GridPolygon>, List <IDoorLine> > >();
            var shapes                 = new List <ConfigurationSpaces <TConfiguration> .WeightedShape>();
            var shapesForNodes         = new Dictionary <int, List <ConfigurationSpaces <TConfiguration> .WeightedShape> >();
            var intAliasMapping        = new Dictionary <int, RoomInfo>();
            var defaultTransformations = new List <Transformation>(mapDescription.GetDefaultTransformations());

            // Handle universal shapes
            foreach (var shape in mapDescription.GetRoomShapes())
            {
                var rotatedShapes = TransformPolygons(shape.RoomDescription, shape.Transformations ?? defaultTransformations).Select(CreateAlias).ToList();
                var probability   = shape.NormalizeProbabilities ? shape.Probability / rotatedShapes.Count : shape.Probability;

                shapes.AddRange(rotatedShapes.Select(x => new ConfigurationSpaces <TConfiguration> .WeightedShape(x.Item1, probability)));
            }

            // Handle shapes for nodes
            foreach (var vertex in graph.Vertices.Where(x => !mapDescription.IsCorridorRoom(x)))
            {
                var shapesForNode = mapDescription.GetRoomShapesForNodes()[vertex];

                if (shapesForNode == null)
                {
                    shapesForNodes.Add(vertex, null);
                    continue;
                }

                var shapesContainer = new List <ConfigurationSpaces <TConfiguration> .WeightedShape>();
                foreach (var shape in shapesForNode)
                {
                    var rotatedShapes = TransformPolygons(shape.RoomDescription, shape.Transformations ?? defaultTransformations).Select(CreateAlias).ToList();
                    var probability   = shape.NormalizeProbabilities ? shape.Probability / rotatedShapes.Count : shape.Probability;

                    shapesContainer.AddRange(rotatedShapes.Select(x => new ConfigurationSpaces <TConfiguration> .WeightedShape(x.Item1, probability)));
                }

                shapesForNodes.Add(vertex, shapesContainer);
            }

            // Corridor shapes
            var corridorShapesContainer = new List <ConfigurationSpaces <TConfiguration> .WeightedShape>();

            foreach (var shape in mapDescription.GetCorridorShapes())
            {
                var rotatedShapes = TransformPolygons(shape.RoomDescription, shape.Transformations ?? defaultTransformations).Select(CreateAlias).ToList();
                var probability   = shape.NormalizeProbabilities ? shape.Probability / rotatedShapes.Count : shape.Probability;

                corridorShapesContainer.AddRange(rotatedShapes.Select(x => new ConfigurationSpaces <TConfiguration> .WeightedShape(x.Item1, probability)));
            }

            // Handle shapes for corridores
            foreach (var vertex in graph.Vertices.Where(mapDescription.IsCorridorRoom))
            {
                shapesForNodes.Add(vertex, corridorShapesContainer);
            }

            // Prepare data structures
            var shapesForNodesArray = new List <ConfigurationSpaces <TConfiguration> .WeightedShape> [shapesForNodes.Count];

            foreach (var pair in shapesForNodes)
            {
                shapesForNodesArray[pair.Key] = pair.Value;
            }

            var configurationSpaces = new ConfigurationSpace[aliasCounter][];

            for (var i = 0; i < aliasCounter; i++)
            {
                var shape1 = allShapes[i];
                configurationSpaces[i] = new ConfigurationSpace[aliasCounter];

                for (var j = 0; j < aliasCounter; j++)
                {
                    var shape2 = allShapes[j];

                    configurationSpaces[i][j] =
                        GetConfigurationSpace(shape1.Item1.Value, shape1.Item2, shape2.Item1.Value, shape2.Item2, offsets);
                }
            }

            if (shapes.Count == 0 && graph.Vertices.Any(x => !shapesForNodes.ContainsKey(x) || shapesForNodes[x] == null || shapesForNodes[x].Count == 0))
            {
                throw new ArgumentException("There must be at least one shape for each node", nameof(mapDescription));
            }

            LastIntAliasMapping = intAliasMapping;

            return(new ConfigurationSpaces <TConfiguration>(shapes, shapesForNodesArray, configurationSpaces, lineIntersection));

            // Return an already existing alias or create a new one
            Tuple <IntAlias <GridPolygon>, List <IDoorLine> > CreateAlias(RoomInfo roomInfo)
            {
                foreach (var pair in allShapes)
                {
                    var otherRoomInfo = intAliasMapping[pair.Key];

                    if (roomInfo.RoomDescription == otherRoomInfo.RoomDescription &&
                        roomInfo.Transformations.SequenceEqualWithoutOrder(otherRoomInfo.Transformations))
                    {
                        return(pair.Value);
                    }
                }

                var alias      = new IntAlias <GridPolygon>(aliasCounter++, roomInfo.RoomShape);
                var aliasTuple = Tuple.Create(alias, roomInfo.DoorLines);

                allShapes.Add(alias.Alias, aliasTuple);
                intAliasMapping.Add(alias.Alias, roomInfo);

                return(aliasTuple);
            }
        }
 /// <inheritdoc />
 public override ConfigurationSpace GetConfigurationSpace(IntAlias <GridPolygon> movingPolygon, IntAlias <GridPolygon> fixedPolygon)
 {
     return(ConfigurationSpaces_[movingPolygon.Alias][fixedPolygon.Alias]);
 }
        private void SetupGenerator()
        {
            var mapping       = levelDescriptionMapped.GetMapping();
            var chainsGeneric = configuration.Chains;

            // Create chain decomposition
            if (chainsGeneric == null)
            {
                var chainDecomposition = new Common.TwoStageChainDecomposition <TRoom>(levelDescription, new BreadthFirstChainDecomposition <TRoom>(configuration.ChainDecompositionConfiguration ?? new ChainDecompositionConfiguration()));
                chainsGeneric = chainDecomposition.GetChains(levelDescription.GetGraph());
            }

            var chains = chainsGeneric
                         .Select(x => new Chain <RoomNode <TRoom> >(x.Nodes.Select(y => mapping[y]).ToList(), x.Number)
            {
                IsFromFace = x.IsFromFace
            })
                         .ToList();

            // Create generator planner
            var generatorPlanner = new GeneratorPlanner <Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >, RoomNode <TRoom> >(configuration.SimulatedAnnealingMaxBranching);

            // Create configuration spaces
            var configurationSpacesGenerator = new ConfigurationSpacesGenerator(
                new PolygonOverlap(),
                DoorHandler.DefaultHandler,
                new OrthogonalLineIntersection(),
                new GridPolygonUtils());

            // var configurationSpaces = configurationSpacesGenerator.GetConfigurationSpaces<ConfigurationNew2<CorridorsDataNew>>(mapDescription);
            var simpleConfigurationSpaces = new ConfigurationSpacesGrid2D <ConfigurationGrid2D <TRoom, EnergyData>, RoomNode <TRoom> >(levelDescriptionMapped);

            // Needlessly complex for backwards compatibility

            #region IntAliasMapping

            var roomDescriptions             = levelDescriptionMapped.GetGraph().Vertices.ToDictionary(x => x, x => (RoomDescriptionGrid2D)levelDescriptionMapped.GetRoomDescription(x));
            var roomTemplates                = roomDescriptions.Values.SelectMany(x => x.RoomTemplates).Distinct().ToList();
            var roomTemplateInstances        = roomTemplates.ToDictionary(x => x, configurationSpacesGenerator.GetRoomTemplateInstances);
            var roomTemplateInstancesMapping = roomTemplateInstances.SelectMany(x => x.Value).CreateIntMapping();
            var intAliasMapping              = new TwoWayDictionary <RoomTemplateInstanceGrid2D, IntAlias <PolygonGrid2D> >();

            foreach (var shape1 in roomTemplateInstancesMapping.Keys)
            {
                foreach (var shape2 in roomTemplateInstancesMapping.Keys)
                {
                    if (!intAliasMapping.ContainsKey(shape1))
                    {
                        var newAlias = new IntAlias <PolygonGrid2D>(intAliasMapping.Count, shape1.RoomShape);
                        intAliasMapping.Add(shape1, newAlias);
                        shape1.RoomShapeAlias = newAlias;
                    }
                    if (!intAliasMapping.ContainsKey(shape2))
                    {
                        var newAlias = new IntAlias <PolygonGrid2D>(intAliasMapping.Count, shape2.RoomShape);
                        intAliasMapping.Add(shape2, newAlias);
                        shape2.RoomShapeAlias = newAlias;
                    }
                }
            }

            // TODO: remove when possible
            foreach (var pair in intAliasMapping)
            {
                pair.Key.RoomShapeAlias = pair.Value;
            }

            var shapesForNodes = new Dictionary <RoomNode <TRoom>, List <WeightedShape> >();
            foreach (var vertex in levelDescriptionMapped.GetGraph().Vertices)
            {
                shapesForNodes.Add(vertex, new List <WeightedShape>());
                // var roomDescription = levelDescriptionMapped.GetRoomDescription(vertex);
                var roomDescription = roomDescriptions[vertex];

                foreach (var roomTemplate in roomDescription.RoomTemplates)
                {
                    var instances = roomTemplateInstances[roomTemplate];

                    foreach (var roomTemplateInstance in instances)
                    {
                        shapesForNodes[vertex].Add(new WeightedShape(intAliasMapping[roomTemplateInstance], 1d / instances.Count));
                    }
                }
            }

            var usedShapes = new HashSet <int>();
            var allShapes  = new List <IntAlias <PolygonGrid2D> >();
            foreach (var vertex in levelDescriptionMapped.GetGraph().Vertices)
            {
                var shapes = shapesForNodes[vertex];

                foreach (var shape in shapes)
                {
                    if (!usedShapes.Contains(shape.Shape.Alias))
                    {
                        allShapes.Add(shape.Shape);
                        usedShapes.Add(shape.Shape.Alias);
                    }
                }
            }

            var averageSize = (int)allShapes.Select(x => x.Value.BoundingRectangle).Average(x => (x.Width + x.Height) / 2);

            #endregion



            // var averageSize = configurationSpaces.GetAverageSize();

            var energyUpdater     = new BasicEnergyUpdater <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData> >(10 * averageSize);
            var roomShapeGeometry = new FastGridPolygonGeometry <ConfigurationGrid2D <TRoom, EnergyData>, RoomNode <TRoom> >();

            // Create generator constraints
            var stageOneConstraints =
                new List <INodeConstraint <ILayout <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData> >, RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>,
                                           EnergyData> >
            {
                new BasicConstraint <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, EnergyData>(
                    roomShapeGeometry,
                    simpleConfigurationSpaces,
                    levelDescriptionMapped,
                    configuration.OptimizeCorridorConstraints
                    ),
                new CorridorConstraint <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, EnergyData>(
                    levelDescriptionMapped,
                    simpleConfigurationSpaces,
                    roomShapeGeometry
                    ),
            };

            if (levelDescription.MinimumRoomDistance > 0)
            {
                stageOneConstraints.Add(new MinimumDistanceConstraint <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, EnergyData>(
                                            levelDescriptionMapped,
                                            roomShapeGeometry,
                                            levelDescription.MinimumRoomDistance
                                            ));
            }

            var constraintsEvaluator = new ConstraintsEvaluator <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, EnergyData>(stageOneConstraints, energyUpdater);

            var roomShapesHandler = new RoomShapesHandlerGrid2D <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData> >(
                intAliasMapping,
                levelDescriptionMapped,
                shapesForNodes,
                levelDescription.RoomTemplateRepeatModeOverride,
                levelDescription.RoomTemplateRepeatModeDefault
                );

            // Create layout operations
            var layoutOperations = new LayoutController <Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >, RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, RoomTemplateInstanceGrid2D, EnergyData>(averageSize, levelDescriptionMapped, constraintsEvaluator, roomShapesHandler, configuration.ThrowIfRepeatModeNotSatisfied, simpleConfigurationSpaces, roomShapeGeometry);

            var initialLayout   = new Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >(levelDescriptionMapped.GetGraph());
            var layoutConverter =
                new BasicLayoutConverterGrid2D <TRoom,
                                                ConfigurationGrid2D <TRoom, EnergyData> >(levelDescription, simpleConfigurationSpaces,
                                                                                          intAliasMapping);

            // Create simulated annealing evolver
            var layoutEvolver =
                new Common.SimulatedAnnealingEvolver <Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >, RoomNode <TRoom>,
                                                      ConfigurationGrid2D <TRoom, EnergyData> >(layoutOperations, configuration.SimulatedAnnealingConfiguration, true);

            // Create the generator itself
            generator = new ChainBasedGenerator <Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >, LayoutGrid2D <TRoom>, RoomNode <TRoom> >(initialLayout, generatorPlanner, chains, layoutEvolver, layoutConverter);

            // Register event handlers
            generator.OnRandomInjected += (random) =>
            {
                // ((IRandomInjectable)configurationSpaces).InjectRandomGenerator(random);
                ((IRandomInjectable)layoutOperations).InjectRandomGenerator(random);
                ((IRandomInjectable)layoutEvolver).InjectRandomGenerator(random);
                ((IRandomInjectable)layoutConverter).InjectRandomGenerator(random);
                ((IRandomInjectable)simpleConfigurationSpaces).InjectRandomGenerator(random);
                ((IRandomInjectable)roomShapesHandler).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));
        }
示例#14
0
 public Configuration(IntAlias <GridPolygon> shape, IntVector2 position, TEnergyData energyData)
 {
     ShapeContainer = shape;
     Position       = position;
     EnergyData     = energyData;
 }
 /// <inheritdoc />
 public override ConfigurationSpace GetConfigurationSpace(IntAlias <PolygonGrid2D> movingPolygon, IntAlias <PolygonGrid2D> fixedPolygon)
 {
     throw new InvalidOperationException();
     return(ConfigurationSpaces_[movingPolygon.Alias][fixedPolygon.Alias][0]);            // TODO: is this ok?
 }