Exemple #1
0
        private bool IsGrounded(TCoord coord, HashSet <TCoord> visited)
        {
            if (visited.Contains(coord) || !coord.IsValid(Model.R) || !this[coord])
            {
                return(false);
            }

            visited.Add(coord);
            if (coord.Y == 0)
            {
                return(true);
            }

            return(coord.ManhattenNeighbours().Any(x => IsGrounded(x, visited)));
        }
Exemple #2
0
 private bool this[TCoord c] => c.IsValid(Model.R) && Matrix[c.X, c.Y, c.Z] > 0;
Exemple #3
0
        public IEnumerable <CoordWithPath> EnumerateReachablePaths(TCoord src, int maxDepth, int maxSteps)
        {
            ++curGeneration;

            // THIS IS VERY DUMB ALGO. BECAUSE I'M TOO STUPID TO DO BETTER

            // TODO: support LMoves
            queue.Clear();
            queue.Enqueue(src);
            cells[src.X, src.Y, src.Z] = new CellData()
            {
                Cost       = 0,
                Generation = curGeneration
            };

            yield return(new CoordWithPath(src, cells));

            int steps = 0;

            while (queue.Count != 0)
            {
                var cur = queue.Dequeue();

                // TODO: smarter precompute?
                var(minDx, maxDx) = FindRange(1, 0, 0);
                var(minDy, maxDy) = FindRange(0, 1, 0);
                var(minDz, maxDz) = FindRange(0, 0, 1);

                var c = default(CoordWithPath);
                // we visit (and yield) closes nodes first
                for (var dx = minDx; dx <= maxDx; ++dx)
                {
                    if (TryVisit(Math.Abs(dx), dx, 0, 0))
                    {
                        yield return(c);

                        if (++steps >= maxSteps)
                        {
                            yield break;
                        }
                        queue.Enqueue(c.Coord);
                    }
                }

                for (var dy = minDy; dy <= maxDy; ++dy)
                {
                    if (TryVisit(Math.Abs(dy), 0, dy, 0))
                    {
                        yield return(c);

                        if (++steps >= maxSteps)
                        {
                            yield break;
                        }
                        queue.Enqueue(c.Coord);
                    }
                }

                for (var dz = minDz; dz <= maxDz; ++dz)
                {
                    if (TryVisit(Math.Abs(dz), 0, 0, dz))
                    {
                        yield return(c);

                        if (++steps >= maxSteps)
                        {
                            yield break;
                        }
                        queue.Enqueue(c.Coord);
                    }
                }

                (int, int) FindRange(int dx, int dy, int dz)
                {
                    var min      = 0;
                    var minCoord = cur;

                    do
                    {
                        minCoord.Apply(new CoordDiff(-1 * dx, -1 * dy, -1 * dz));
                        --min;
                    }while ((min >= -Constants.StraightMoveCorrection) && minCoord.IsValid(model.R) && IsFree(minCoord, maxDepth));

                    var max      = 0;
                    var maxCoord = cur;

                    do
                    {
                        maxCoord.Apply(new CoordDiff(dx, dy, dz));
                        ++max;
                    }while ((max <= Constants.StraightMoveCorrection) && maxCoord.IsValid(model.R) && IsFree(maxCoord, maxDepth));

                    return(min + 1, max - 1);
                }

                bool TryVisit(int dist, int dx, int dy, int dz)
                {
                    var next    = new TCoord(cur.X + dx, cur.Y + dy, cur.Z + dz);
                    var curCost = cells[cur.X, cur.Y, cur.Z].Cost;

                    if (next.IsValid(model.R) && !cells[next.X, next.Y, next.Z].Visited(curGeneration))
                    {
                        // TODO: add energy maintainance into cost
                        cells[next.X, next.Y, next.Z] = new CellData()
                        {
                            From       = cur,
                            Cost       = curCost + (2 * dist),
                            Generation = curGeneration,
                        };
                        c = new CoordWithPath(next, cells);
                        return(true);

                        // if (!IsFree(next)) throw new Exception("WTF");
                    }

                    return(false);
                }
            }
        }