private static bool CheckSpawn(CritterSpawn spawn, bool onEntry)
        {
            // Must be in the right location.
            var location = Game1.player.currentLocation;

            if (location.Name != spawn.Location)
            {
                return(false);
            }

            // Random roll must succeed.
            if (!(Game1.random.NextDouble() <
                  (onEntry ? spawn.ChanceOnEntry : spawn.ChanceOnTick)))
            {
                return(false);
            }

            // Conditions must hold.
            if (!spawn.Conditions.check())
            {
                return(false);
            }

            // Roll for number of clusters to spawn.
            int clusters = Game1.random.Next(spawn.MinClusters, spawn.MaxClusters + 1);

            if (clusters < 1)
            {
                return(false);
            }

            // Spawn the clusters.
            for (int i = 0; i < clusters; ++i)
            {
                SpawnCluster(spawn, location);
            }
            return(true);
        }
        private static void SpawnCluster(CritterSpawn spawn, GameLocation location)
        {
            // Randomly find a center position within the area.
            Rectangle area   = spawn.adjustArea(location);
            int       x      = Game1.random.Next(area.Left, area.Right + 1);
            int       y      = Game1.random.Next(area.Top, area.Bottom + 1);
            Vector2   center = new (x, y);

            // Roll for number of critters to spawn.
            int count = Game1.random.Next(spawn.MinPerCluster, spawn.MaxPerCluster + 1);

            if (count < 1)
            {
                return;
            }

            // Spawn the critters.
            Monitor.Log($"Spawning cluster of up to {count} critter(s) in location '{location.Name}' around ({x},{y}).",
                        LogLevel.Trace);
            foreach (Vector2 tile in Utility.getPositionsInClusterAroundThisTile(center, count))
            {
                // Don't veer off the map.
                if (!location.isTileOnMap(tile))
                {
                    continue;
                }

                // Tile must be clear, except allow water tiles with specified chance.
                bool onWater = location.doesTileHaveProperty((int)tile.X, (int)tile.Y, "Water", "Back") != null;
                if (!location.isTileLocationTotallyClearAndPlaceable(tile))
                {
                    if (!onWater || !(Game1.random.NextDouble() < spawn.ChanceOnWater))
                    {
                        continue;
                    }
                }

                // Spawn the critter.
                Critter critter = spawn.Type switch
                {
                    CritterType.BrownBird =>
                    new Birdie((int)tile.X, (int)tile.Y, Birdie.brownBird),
                    CritterType.BlueBird =>
                    new Birdie((int)tile.X, (int)tile.Y, Birdie.blueBird),
                    CritterType.SpecialBlueBird =>
                    new Birdie((int)tile.X, (int)tile.Y, 125),
                    CritterType.SpecialRedBird =>
                    new Birdie((int)tile.X, (int)tile.Y, 135),
                    CritterType.Butterfly =>
                    new Butterfly(tile),
                    CritterType.IslandButterfly =>
                    new Butterfly(tile, true),
                    CritterType.CalderaMonkey =>
                    new CalderaMonkey(tile * 64f),
                    CritterType.Cloud =>
                    new Cloud(tile),
                    CritterType.Crab =>
                    new CrabCritter(tile * 64f),
                    CritterType.Crow =>
                    new Crow((int)tile.X, (int)tile.Y),
                    CritterType.Firefly =>
                    new Firefly(tile),
                    CritterType.Frog =>
                    new Frog(tile, waterLeaper: onWater, forceFlip: Game1.random.NextDouble() < 0.5),
                    CritterType.OverheadParrot =>
                    new OverheadParrot(tile * 64f),
                    CritterType.Owl =>
                    new Owl(tile * 64f),
                    CritterType.Rabbit =>
                    new Rabbit(tile, flip: Game1.random.NextDouble() < 0.5),
                    CritterType.Seagull =>
                    new Seagull(tile * 64f + new Vector2(32f, 32f), startingState: onWater ? 2 : 3),
                    CritterType.Squirrel =>
                    new Squirrel(tile, flip: Game1.random.NextDouble() < 0.5),
                    _ => null,
                };
                if (critter != null)
                {
                    location.critters.Add(critter);
                }
            }
        }