Exemple #1
0
        private static bool Path(CreatureMovement mover, Voxel start, GoalRegion goal, ChunkManager chunks, int maxExpansions, ref List <Creature.MoveAction> toReturn, bool reverse)
        {
            VoxelChunk startChunk = chunks.ChunkData.ChunkMap[start.ChunkID];
            VoxelChunk endChunk   = chunks.ChunkData.ChunkMap[goal.GetVoxel().ChunkID];

            if (startChunk.IsCompletelySurrounded(start) || endChunk.IsCompletelySurrounded(goal.GetVoxel()))
            {
                toReturn = null;
                return(false);
            }


            HashSet <Voxel> closedSet = new HashSet <Voxel>();

            HashSet <Voxel> openSet = new HashSet <Voxel>
            {
                start
            };

            Dictionary <Voxel, Creature.MoveAction> cameFrom = new Dictionary <Voxel, Creature.MoveAction>();
            Dictionary <Voxel, float> gScore = new Dictionary <Voxel, float>();
            PriorityQueue <Voxel>     fScore = new PriorityQueue <Voxel>();

            gScore[start] = 0.0f;
            fScore.Enqueue(start, gScore[start] + Heuristic(start, goal.GetVoxel()));

            int numExpansions = 0;

            List <Voxel> manhattanNeighbors = new List <Voxel>(6);

            for (int i = 0; i < 6; i++)
            {
                manhattanNeighbors.Add(new Voxel());
            }
            while (openSet.Count > 0 && numExpansions < maxExpansions)
            {
                Voxel current = GetVoxelWithMinimumFScore(fScore, openSet);

                if (current == null)
                {
                    current = start;
                    numExpansions++;
                }
                numExpansions++;
                if (goal.IsInGoalRegion(current))
                {
                    Creature.MoveAction first = new Creature.MoveAction()
                    {
                        Voxel    = current,
                        MoveType = Creature.MoveType.Walk
                    };
                    toReturn = ReconstructPath(cameFrom, first);
                    return(true);
                }

                openSet.Remove(current);
                closedSet.Add(current);

                VoxelChunk currentChunk = chunks.ChunkData.ChunkMap[current.ChunkID];

                List <Creature.MoveAction> neighbors = null;

                neighbors = mover.GetMoveActions(current);
                currentChunk.GetNeighborsManhattan(current, manhattanNeighbors);

                if (manhattanNeighbors.Contains(goal.GetVoxel()))
                {
                    Creature.MoveAction first = new Creature.MoveAction()
                    {
                        Voxel    = current,
                        MoveType = Creature.MoveType.Walk
                    };
                    Creature.MoveAction last = new Creature.MoveAction()
                    {
                        Voxel    = goal.GetVoxel(),
                        MoveType = Creature.MoveType.Walk
                    };
                    List <Creature.MoveAction> subPath = ReconstructPath(cameFrom, first);
                    subPath.Add(last);
                    toReturn = subPath;
                    return(true);
                }

                foreach (Creature.MoveAction n in neighbors)
                {
                    if (closedSet.Contains(n.Voxel))
                    {
                        continue;
                    }

                    float tenativeGScore = gScore[current] + GetDistance(current, n.Voxel, n.MoveType, chunks);

                    if (openSet.Contains(n.Voxel) && !(tenativeGScore < gScore[n.Voxel]))
                    {
                        continue;
                    }

                    openSet.Add(n.Voxel);
                    Creature.MoveAction cameAction = n;
                    cameAction.Voxel = current;

                    cameFrom[n.Voxel] = cameAction;
                    gScore[n.Voxel]   = tenativeGScore;
                    fScore.Enqueue(n.Voxel, gScore[n.Voxel] + Heuristic(n.Voxel, goal.GetVoxel()));
                }

                if (numExpansions >= maxExpansions)
                {
                    return(false);
                }
            }
            toReturn = null;
            return(false);
        }
Exemple #2
0
        /// <summary>
        ///     Creates a path from the start voxel to some goal region, returning a list of movements that can
        ///     take a mover from the start voxel to the goal region.
        /// </summary>
        /// <param name="mover">The agent that we want to find a path for.</param>
        /// <param name="start">The voxel that the agent starts in.</param>
        /// <param name="goal">Goal conditions that the agent is trying to satisfy.</param>
        /// <param name="chunks">The voxels that the agent is moving through</param>
        /// <param name="maxExpansions">Maximum number of voxels to consider before giving up.</param>
        /// <param name="toReturn">The path of movements that the mover should take to reach the goal.</param>
        /// <param name="weight">
        ///     A heuristic weight to apply to the planner. If 1.0, the path is garunteed to be optimal. Higher values
        ///     usually result in faster plans that are suboptimal.
        /// </param>
        /// <returns>True if a path could be found, or false otherwise.</returns>
        private static bool Path(CreatureMovement mover, Voxel start, GoalRegion goal, ChunkManager chunks,
                                 int maxExpansions, ref List <Creature.MoveAction> toReturn, float weight)
        {
            // Sometimes a goal may not even be achievable a.priori. If this is true, we know there can't be a path
            // which satisifies that goal.
            if (!goal.IsPossible())
            {
                toReturn = null;
                return(false);
            }

            // Voxels that have already been explored.
            var closedSet = new HashSet <Voxel>();

            // Voxels which should be explored.
            var openSet = new HashSet <Voxel>
            {
                start
            };

            // Dictionary of voxels to the optimal action that got the mover to that voxel.
            var cameFrom = new Dictionary <Voxel, Creature.MoveAction>();

            // Optimal score of a voxel based on the path it took to get there.
            var gScore = new Dictionary <Voxel, float>();

            // Expansion priority of voxels.
            var fScore = new PriorityQueue <Voxel>();

            // Starting conditions of the search.
            gScore[start] = 0.0f;
            fScore.Enqueue(start, gScore[start] + weight * goal.Heuristic(start));

            // Keep count of the number of expansions we've taken to get to the goal.
            int numExpansions = 0;

            // Check the voxels adjacent to the current voxel as a quick test of adjacency to the goal.
            var manhattanNeighbors = new List <Voxel>(6);

            for (int i = 0; i < 6; i++)
            {
                manhattanNeighbors.Add(new Voxel());
            }

            // Loop until we've either checked every possible voxel, or we've exceeded the maximum number of
            // expansions.
            while (openSet.Count > 0 && numExpansions < maxExpansions)
            {
                // Check the next voxel to explore.
                Voxel current = GetVoxelWithMinimumFScore(fScore);
                if (current == null)
                {
                    // If there wasn't a voxel to explore, just try to expand from
                    // the start again.
                    current = start;
                    numExpansions++;
                }
                numExpansions++;

                // If we've reached the goal already, reconstruct the path from the start to the
                // goal.
                if (goal.IsInGoalRegion(current))
                {
                    // Assume that the last action in the path involves walking to the goal.
                    var first = new Creature.MoveAction
                    {
                        Voxel    = current,
                        MoveType = Creature.MoveType.Walk
                    };
                    toReturn = ReconstructPath(cameFrom, first);
                    return(true);
                }

                // We've already considered the voxel, so add it to the closed set.
                openSet.Remove(current);
                closedSet.Add(current);

                VoxelChunk currentChunk = chunks.ChunkData.ChunkMap[current.ChunkID];

                List <Creature.MoveAction> neighbors = null;

                // Get the voxels that can be moved to from the current voxel.
                neighbors = mover.GetMoveActions(current);
                currentChunk.GetNeighborsManhattan(current, manhattanNeighbors);

                // A quick test to see if we're already adjacent to the goal. If we are, assume
                // that we can just walk to it.
                if (manhattanNeighbors.Contains(goal.GetVoxel()))
                {
                    var first = new Creature.MoveAction
                    {
                        Voxel    = current,
                        MoveType = Creature.MoveType.Walk
                    };
                    var last = new Creature.MoveAction
                    {
                        Voxel    = goal.GetVoxel(),
                        MoveType = Creature.MoveType.Walk
                    };
                    List <Creature.MoveAction> subPath = ReconstructPath(cameFrom, first);
                    subPath.Add(last);
                    toReturn = subPath;
                    return(true);
                }

                // Otherwise, consider all of the neighbors of the current voxel that can be moved to,
                // and determine how to add them to the list of expansions.
                foreach (Creature.MoveAction n in neighbors)
                {
                    // If we've already explored that voxel, don't explore it again.
                    if (closedSet.Contains(n.Voxel))
                    {
                        continue;
                    }

                    // Otherwise, consider the case of moving to that neighbor.
                    float tenativeGScore = gScore[current] + GetDistance(current, n.Voxel, n.MoveType, mover);

                    // IF the neighbor can already be reached more efficiently, ignore it.
                    if (openSet.Contains(n.Voxel) && !(tenativeGScore < gScore[n.Voxel]))
                    {
                        continue;
                    }

                    // Otherwise, add it to the list of voxels for consideration.
                    openSet.Add(n.Voxel);

                    // Add an edge to the voxel from the current voxel.
                    Creature.MoveAction cameAction = n;
                    cameAction.Voxel  = current;
                    cameFrom[n.Voxel] = cameAction;

                    // Update the expansion scores for the next voxel.
                    gScore[n.Voxel] = tenativeGScore;
                    fScore.Enqueue(n.Voxel, gScore[n.Voxel] + weight * goal.Heuristic(n.Voxel));
                }

                // If we've expanded too many voxels, just give up.
                if (numExpansions >= maxExpansions)
                {
                    return(false);
                }
            }

            // Somehow we've reached this code without having found a path. Return false.
            toReturn = null;
            return(false);
        }
        public void GenerateCaves(VoxelChunk chunk)
        {
            Vector3      origin     = chunk.Origin;
            int          chunkSizeX = chunk.SizeX;
            int          chunkSizeY = chunk.SizeY;
            int          chunkSizeZ = chunk.SizeZ;
            BiomeData    biome      = BiomeLibrary.Biomes[Overworld.Biome.Cave];
            List <Voxel> neighbors  = new List <Voxel>();
            Voxel        vUnder     = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunkSizeX; x++)
            {
                for (int z = 0; z < chunkSizeZ; z++)
                {
                    int h = chunk.GetFilledVoxelGridHeightAt(x, chunk.SizeY - 1, z);
                    for (int i = 0; i < CaveLevels.Count; i++)
                    {
                        int y = CaveLevels[i];
                        if (y <= 0 || y >= h - 1)
                        {
                            continue;
                        }
                        Vector3 vec       = new Vector3(x, y, z) + chunk.Origin;
                        double  caveNoise = CaveNoise.GetValue((x + origin.X) * CaveNoiseScale * CaveFrequencies[i],
                                                               (y + origin.Y) * CaveNoiseScale * 3.0f, (z + origin.Z) * CaveNoiseScale * CaveFrequencies[i]);

                        double heightnoise = NoiseGenerator.Noise((x + origin.X) * NoiseScale * CaveFrequencies[i],
                                                                  (y + origin.Y) * NoiseScale * 3.0f, (z + origin.Z) * NoiseScale * CaveFrequencies[i]);

                        int caveHeight = Math.Min(Math.Max((int)(heightnoise * 5), 1), 3);

                        if (caveNoise > CaveSize)
                        {
                            bool waterFound = false;
                            for (int dy = 0; dy < caveHeight; dy++)
                            {
                                int index = chunk.Data.IndexAt(x, y - dy, z);
                                chunk.GetNeighborsManhattan(x, y - dy, z, neighbors);

                                if (neighbors.Any(v => v.WaterLevel > 0))
                                {
                                    waterFound = true;
                                }

                                if (waterFound)
                                {
                                    break;
                                }

                                chunk.Data.Types[index] = 0;
                            }

                            if (!waterFound && caveNoise > CaveSize * 1.8f && y - caveHeight > 0)
                            {
                                int indexunder = chunk.Data.IndexAt(x, y - caveHeight, z);
                                chunk.Data.Types[indexunder]      = (byte)VoxelLibrary.GetVoxelType(biome.GrassVoxel).ID;
                                chunk.Data.Health[indexunder]     = (byte)VoxelLibrary.GetVoxelType(biome.GrassVoxel).StartingHealth;
                                chunk.Data.IsExplored[indexunder] = false;
                                foreach (VegetationData veg in biome.Vegetation)
                                {
                                    if (!MathFunctions.RandEvent(veg.SpawnProbability))
                                    {
                                        continue;
                                    }

                                    if (NoiseGenerator.Noise(vec.X / veg.ClumpSize, veg.NoiseOffset, vec.Y / veg.ClumpSize) < veg.ClumpThreshold)
                                    {
                                        continue;
                                    }


                                    vUnder.GridPosition = new Vector3(x, y - 1, z);
                                    if (!vUnder.IsEmpty && vUnder.TypeName == biome.GrassVoxel)
                                    {
                                        vUnder.Type = VoxelLibrary.GetVoxelType(biome.SoilVoxel);
                                        float offset = veg.VerticalOffset;
                                        if (vUnder.RampType != RampType.None)
                                        {
                                            offset -= 0.25f;
                                        }
                                        float         treeSize = MathFunctions.Rand() * veg.SizeVariance + veg.MeanSize;
                                        GameComponent entity   = EntityFactory.CreateEntity <GameComponent>(veg.Name, chunk.Origin + new Vector3(x, y, z) + new Vector3(0, treeSize * offset, 0), Blackboard.Create("Scale", treeSize));
                                        entity.GetRootComponent().SetActiveRecursive(false);
                                        entity.GetRootComponent().SetVisibleRecursive(false);
                                        if (GameSettings.Default.FogofWar)
                                        {
                                            ExploredListener listener = new ExploredListener(
                                                PlayState.ComponentManager, entity, PlayState.ChunkManager, vUnder);
                                        }
                                    }
                                }
                            }

                            foreach (FaunaData animal in biome.Fauna)
                            {
                                if (y <= 0 || !(PlayState.Random.NextDouble() < animal.SpawnProbability))
                                {
                                    continue;
                                }


                                var entity = EntityFactory.CreateEntity <GameComponent>(animal.Name, chunk.Origin + new Vector3(x, y, z) + Vector3.Up * 1.0f);
                                entity.GetRootComponent().SetActiveRecursive(false);
                                entity.GetRootComponent().SetVisibleRecursive(false);

                                if (GameSettings.Default.FogofWar)
                                {
                                    ExploredListener listener = new ExploredListener(PlayState.ComponentManager, entity,
                                                                                     PlayState.ChunkManager, chunk.MakeVoxel(x, y, z));
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }