/// <inheritdoc />
        public bool ComputeEnergyData(TLayout layout, TNode node, TConfiguration configuration, ref TEnergyData energyData)
        {
            if (mapDescription.IsCorridorRoom(node))
            {
                return(true);
            }

            var distance   = 0;
            var neighbours = graphWithoutCorridors.GetNeighbours(node).ToList();

            foreach (var vertex in neighbours)
            {
                if (vertex.Equals(node))
                {
                    continue;
                }

                if (!layout.GetConfiguration(vertex, out var c))
                {
                    continue;
                }

                if (!configurationSpaces.HaveValidPosition(configuration, c))
                {
                    distance += ComputeDistance(configuration, c);
                }
            }

            var energy = ComputeEnergy(0, distance);

            energyData.CorridorDistance = distance;
            energyData.Energy          += energy;

            return(distance == 0);
        }
示例#2
0
        /// <summary>
        /// Perturbs non corridor rooms until a valid layout is found.
        /// Then tries to use a greedy algorithm to lay out corridor rooms.
        /// </summary>
        /// <param name="layout"></param>
        /// <param name="chain"></param>
        /// <param name="updateLayout"></param>
        public override void PerturbLayout(TLayout layout, IList <TNode> chain, bool updateLayout)
        {
            if (!MapDescription.IsWithCorridors)
            {
                base.PerturbLayout(layout, chain, updateLayout);
                return;
            }

            var nonCorridors  = chain.Where(x => !MapDescription.IsCorridorRoom(x)).ToList();
            var firstCorridor = chain.First(x => MapDescription.IsCorridorRoom(x));

            if (layout.GetConfiguration(firstCorridor, out var _))
            {
                foreach (var corridor in chain.Where(x => MapDescription.IsCorridorRoom(x)))
                {
                    layout.RemoveConfiguration(corridor);
                }
            }

            if (Random.NextDouble() < 0.4f)
            {
                PerturbShape(layout, nonCorridors, updateLayout);
            }
            else
            {
                var random = nonCorridors.GetRandom(Random);
                PerturbNonCorridorPosition(layout, random, updateLayout);
            }
        }
示例#3
0
        /// <inheritdoc />
        public bool ComputeEnergyData(TLayout layout, TNode node, TConfiguration configuration, ref TEnergyData energyData)
        {
            if (mapDescription.IsCorridorRoom(node))
            {
                return(true);
            }

            var numberOfTouching = 0;

            foreach (var vertex in layout.Graph.Vertices)
            {
                if (vertex.Equals(node))
                {
                    continue;
                }

                if (!layout.GetConfiguration(vertex, out var c))
                {
                    continue;
                }

                if (mapDescription.IsCorridorRoom(vertex))
                {
                    continue;
                }

                if (DoTouch(configuration, c))
                {
                    numberOfTouching++;
                }
            }

            energyData.NumberOfTouching = numberOfTouching;
            energyData.Energy          += numberOfTouching;

            return(numberOfTouching == 0);
        }
        /// <inheritdoc />
        /// <summary>
        /// Finds the smallest feasible multiple of a specified number and then make from it a sequence of corridors.
        /// </summary>
        public void AddCorridorsToMapping(ICorridorMapDescription <int> mapDescription, TwoWayDictionary <int, int> mapping)
        {
            var graph                = mapDescription.GetGraph();
            var corridors            = graph.Vertices.Where(mapDescription.IsCorridorRoom).ToList();
            var maxNonCorridorNumber = graph.Vertices.Where(x => !mapDescription.IsCorridorRoom(x)).Max();

            var parts      = maxNonCorridorNumber / roundTo;
            var nextNumber = roundTo * (parts + 1);
            var counter    = nextNumber;

            foreach (var corridor in corridors)
            {
                mapping.Add(counter++, corridor);
            }
        }
        /// <inheritdoc />
        public List <List <TNode> > GetChains(IGraph <TNode> graph)
        {
            if (!mapDescription.IsWithCorridors)
            {
                throw new InvalidOperationException("Map description must be with corridors to use this decomposition.");
            }

            var graphWithoutCorridors = mapDescription.GetGraphWithoutCorrridors();
            var faces = decomposition.GetChains(graphWithoutCorridors);

            var usedVertices = new HashSet <TNode>();
            var corridors    = graph.Vertices.Where(x => mapDescription.IsCorridorRoom(x)).ToList();

            foreach (var face in faces)
            {
                face.ForEach(x => usedVertices.Add(x));

                var corridorsToRemove = new List <TNode>();
                foreach (var corridor in corridors)
                {
                    var neighbours = graph.GetNeighbours(corridor).ToList();

                    if (neighbours.Count != 2)
                    {
                        throw new ArgumentException("Every corridor must have exactly two neighbours");
                    }

                    if (usedVertices.Contains(neighbours[0]) && usedVertices.Contains(neighbours[1]))
                    {
                        corridorsToRemove.Add(corridor);
                        face.Add(corridor);
                    }
                }
                corridorsToRemove.ForEach(x => corridors.Remove(x));
            }

            if (corridors.Count != 0)
            {
                throw new ArgumentException();
            }

            return(faces);
        }