public Point GetRandomPoint(TilePropagator propagator, TilePropagatorTileSet tileSet)
        {
            var topology = propagator.Topology;

            var points = new List <Point>();

            for (var z = 0; z < topology.Depth; z++)
            {
                for (var y = 0; y < topology.Height; y++)
                {
                    for (var x = 0; x < topology.Width; x++)
                    {
                        if (topology.Mask != null)
                        {
                            var index = topology.GetIndex(x, y, z);
                            if (!topology.Mask[index])
                            {
                                continue;
                            }
                        }

                        propagator.GetBannedSelected(x, y, z, tileSet, out var isBanned, out var _);
                        if (isBanned)
                        {
                            continue;
                        }

                        points.Add(new Point(x, y, z));
                    }
                }
            }

            // Choose a random point to select
            if (points.Count == 0)
            {
                throw new System.Exception($"No legal placement of {tileSet}");
            }

            var i = (int)(propagator.RandomDouble() * points.Count);

            return(points[i]);
        }
Example #2
0
        public void Init(TilePropagator propagator)
        {
            tileSet = propagator.CreateTileSet(Tiles);

            countTracker = new CountTracker(propagator.Topology);

            selectedChangeTracker = propagator.CreateSelectedChangeTracker(tileSet, countTracker);

            if (Eager)
            {
                // Naive implementation

                /*
                 * // Pick Count random indices
                 * var topology = propagator.Topology;
                 * var pickedIndices = new List<int>();
                 * var remainingIndices = new List<int>(topology.Indicies);
                 * for (var c = 0; c < Count; c++)
                 * {
                 *  var pickedIndexIndex = (int)(propagator.RandomDouble() * remainingIndices.Count);
                 *  pickedIndices.Add(remainingIndices[pickedIndexIndex]);
                 *  remainingIndices[pickedIndexIndex] = remainingIndices[remainingIndices.Count - 1];
                 *  remainingIndices.RemoveAt(remainingIndices.Count - 1);
                 * }
                 * // Ban or select tiles to ensure an appropriate count
                 * if(Comparison == CountComparison.AtMost || Comparison == CountComparison.Exactly)
                 * {
                 *  foreach (var i in remainingIndices)
                 *  {
                 *      topology.GetCoord(i, out var x, out var y, out var z);
                 *      propagator.Ban(x, y, z, tileSet);
                 *  }
                 * }
                 * if (Comparison == CountComparison.AtLeast || Comparison == CountComparison.Exactly)
                 * {
                 *  foreach (var i in pickedIndices)
                 *  {
                 *      topology.GetCoord(i, out var x, out var y, out var z);
                 *      propagator.Select(x, y, z, tileSet);
                 *  }
                 * }
                 */

                var topology         = propagator.Topology;
                var width            = topology.Width;
                var height           = topology.Height;
                var depth            = topology.Depth;
                var pickedIndices    = new List <int>();
                var remainingIndices = new List <int>(topology.GetIndices());

                while (true)
                {
                    var noCount   = 0;
                    var yesCount  = 0;
                    var maybeList = new List <int>();
                    for (var z = 0; z < depth; z++)
                    {
                        for (var y = 0; y < height; y++)
                        {
                            for (var x = 0; x < width; x++)
                            {
                                var index = topology.GetIndex(x, y, z);
                                if (topology.ContainsIndex(index))
                                {
                                    var selected = selectedChangeTracker.GetQuadstate(index);
                                    if (selected.IsNo())
                                    {
                                        noCount++;
                                    }
                                    if (selected.IsMaybe())
                                    {
                                        maybeList.Add(index);
                                    }
                                    if (selected.IsYes())
                                    {
                                        yesCount++;
                                    }
                                }
                            }
                        }
                    }
                    var maybeCount = maybeList.Count;

                    if (Comparison == CountComparison.AtMost)
                    {
                        if (yesCount > Count)
                        {
                            // Already got too many, just fail
                            propagator.SetContradiction();
                            return;
                        }
                        if (yesCount == Count)
                        {
                            // We've reached the limit, ban any more and exit
                            Check(propagator);
                            return;
                        }
                        var pickedIndex = maybeList[(int)(propagator.RandomDouble() * maybeList.Count)];
                        topology.GetCoord(pickedIndex, out var x, out var y, out var z);
                        propagator.Select(x, y, z, tileSet);
                    }
                    else if (Comparison == CountComparison.AtLeast || Comparison == CountComparison.Exactly)
                    {
                        if (yesCount + maybeCount < Count)
                        {
                            // Already got too few, just fail
                            propagator.SetContradiction();
                            return;
                        }
                        if (yesCount + maybeCount == Count)
                        {
                            // We've reached the limit, ban any more and exit
                            Check(propagator);
                            return;
                        }
                        var pickedIndex = maybeList[(int)(propagator.RandomDouble() * maybeList.Count)];
                        topology.GetCoord(pickedIndex, out var x, out var y, out var z);
                        propagator.Ban(x, y, z, tileSet);
                    }
                }
            }
        }