/// <summary>
        /// Sets the ToString information for the given crops
        /// </summary>
        /// <param name="editedObjectInfo">The object info containing changes to apply</param>
        /// <param name="crops">The crops to set</param>
        /// <param name="randomNames">The random names to give the crops</param>
        private static void SetCropAndSeedInformation(
            EditedObjectInformation editedObjectInfo,
            List <CropItem> crops,
            List <string> randomNames,
            List <string> randomDescriptions)
        {
            for (int i = 0; i < crops.Count; i++)
            {
                CropItem crop        = crops[i];
                string   name        = randomNames[i];
                string   description = Globals.RNGGetAndRemoveRandomValueFromList(randomDescriptions);
                crop.OverrideName = name;
                crop.Description  = description;

                SeedItem seed = ItemList.GetSeedFromCrop(crop);
                seed.OverrideDisplayName = seed.CropGrowthInfo.IsTrellisCrop ?
                                           Globals.GetTranslation("trellis-text", new { itemName = name }) :
                                           Globals.GetTranslation("seed-text", new { itemName = name });
                seed.OverrideName = seed.CropGrowthInfo.IsTrellisCrop ?
                                    $"{name} Starter" :
                                    $"{name} Seeds";

                seed.Price = GetRandomSeedPrice();
                crop.Price = CalculateCropPrice(seed);

                if (!Globals.Config.RandomizeCrops)
                {
                    continue;
                }

                editedObjectInfo.ObjectInformationReplacements[crop.Id] = crop.ToString();
                editedObjectInfo.ObjectInformationReplacements[seed.Id] = seed.ToString();
            }
        }
        /// <summary>
        /// Gets a random file name that matches the crop growth image at the given position
        /// Will remove the name found from the list
        /// </summary>
        /// <param name="position">The position</param>
        /// <returns>The selected file name</returns>
        protected override string GetRandomFileName(Point position)
        {
            string fileName = "";

            int  cropId = CropGrowthImagePointsToIds[position];
            Item item   = ItemList.Items[cropId];

            SeedItem seedItem = item.Id == (int)ObjectIndexes.CoffeeBean ?
                                (SeedItem)item : ((CropItem)item).MatchingSeedItem;
            CropGrowthInformation growthInfo = seedItem.CropGrowthInfo;

            FixWidthValue(seedItem.CropGrowthInfo.GraphicId);

            if (item.IsFlower)
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(FlowerImages);

                if (!seedItem.CropGrowthInfo.TintColorInfo.HasTint)
                {
                    fileName = $"{fileName.Substring(0, fileName.Length - 4)}-NoHue.png";
                }
            }

            else if (growthInfo.IsTrellisCrop)
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(TrellisImages);
            }

            else if (growthInfo.RegrowsAfterHarvest)
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(RegrowingImages);
            }

            else
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(NormalImages);

                if (growthInfo.GrowthStages.Count <= 4)
                {
                    fileName += "-4.png";
                }

                else
                {
                    fileName += "-5.png";
                }
            }

            if (string.IsNullOrEmpty(fileName) || fileName == "-4.png" || fileName == "-5.png")
            {
                Globals.ConsoleWarn($"Using default image for crop growth - you may not have enough crop growth images: {position.X}, {position.Y}");
                return(null);
            }


            CropIdsToImageNames[cropId] = Path.GetFileName(fileName).Replace("-4.png", ".png").Replace("-5.png", ".png").Replace("-NoHue.png", ".png");
            return(fileName);
        }
        /// <summary>
        /// Creates a bundle for the pantry
        /// </summary>
        protected override void Populate()
        {
            BundleType = Globals.RNGGetAndRemoveRandomValueFromList(RoomBundleTypes);
            List <RequiredItem> potentialItems = new List <RequiredItem>();

            switch (BundleType)
            {
            case BundleTypes.PantryAnimal:
                Name           = Globals.GetTranslation("bundle-pantry-animal");
                potentialItems = RequiredItem.CreateList(ItemList.GetAnimalProducts());
                potentialItems.Add(new RequiredItem((int)ObjectIndexes.Hay, 25, 50));
                RequiredItems        = Globals.RNGGetRandomValuesFromList(potentialItems, Range.GetRandomValue(6, 8));
                MinimumRequiredItems = Range.GetRandomValue(RequiredItems.Count - 2, RequiredItems.Count);
                Color = BundleColors.Orange;
                break;

            case BundleTypes.PantryQualityCrops:
                Name           = Globals.GetTranslation("bundle-pantry-quality-crops");
                potentialItems = RequiredItem.CreateList(ItemList.GetCrops());
                potentialItems.ForEach(x => x.MinimumQuality = ItemQualities.Gold);
                RequiredItems        = Globals.RNGGetRandomValuesFromList(potentialItems, 8);
                MinimumRequiredItems = Range.GetRandomValue(4, 6);
                Color = BundleColors.Green;
                break;

            case BundleTypes.PantryQualityForagables:
                Name           = Globals.GetTranslation("bundle-pantry-quality-foragables");
                potentialItems = RequiredItem.CreateList(ItemList.GetForagables());
                potentialItems.ForEach(x => x.MinimumQuality = ItemQualities.Gold);
                RequiredItems        = Globals.RNGGetRandomValuesFromList(potentialItems, 8);
                MinimumRequiredItems = Range.GetRandomValue(4, 6);
                Color = BundleColors.Green;
                break;

            case BundleTypes.PantryCooked:
                Name                 = Globals.GetTranslation("bundle-pantry-cooked");
                potentialItems       = RequiredItem.CreateList(ItemList.GetCookeditems());
                RequiredItems        = Globals.RNGGetRandomValuesFromList(potentialItems, Range.GetRandomValue(6, 8));
                MinimumRequiredItems = Range.GetRandomValue(3, 4);
                Color                = BundleColors.Green;
                break;

            case BundleTypes.PantryFlower:
                Name                 = Globals.GetTranslation("bundle-pantry-flower");
                potentialItems       = RequiredItem.CreateList(ItemList.GetFlowers());
                RequiredItems        = Globals.RNGGetRandomValuesFromList(potentialItems, Range.GetRandomValue(6, 8));
                MinimumRequiredItems = RequiredItems.Count - 2;
                Color                = BundleColors.Green;
                break;

            case BundleTypes.PantrySpringCrops:
                GenerateBundleForSeasonCrops(Seasons.Spring, BundleColors.Green);
                break;

            case BundleTypes.PantrySummerCrops:
                GenerateBundleForSeasonCrops(Seasons.Summer, BundleColors.Red);
                break;

            case BundleTypes.PantryFallCrops:
                GenerateBundleForSeasonCrops(Seasons.Fall, BundleColors.Orange);
                break;

            case BundleTypes.PantryEgg:
                Name           = Globals.GetTranslation("bundle-pantry-egg");
                potentialItems = RequiredItem.CreateList(
                    ItemList.Items.Values.Where(x => x.Name.Contains("Egg") && x.Id > -4).ToList());
                RequiredItems        = Globals.RNGGetRandomValuesFromList(potentialItems, 8);
                MinimumRequiredItems = Range.GetRandomValue(RequiredItems.Count - 3, RequiredItems.Count - 2);
                Color = BundleColors.Yellow;
                break;

            case BundleTypes.PantryRareFoods:
                Name = Globals.GetTranslation("bundle-pantry-rare-foods");

                SeedItem starFruitSeed = (SeedItem)ItemList.Items[(int)ObjectIndexes.StarfruitSeeds];
                SeedItem gemBerrySeed  = (SeedItem)ItemList.Items[(int)ObjectIndexes.RareSeed];
                RequiredItems = new List <RequiredItem>
                {
                    new RequiredItem((int)ObjectIndexes.AncientFruit),
                    new RequiredItem(starFruitSeed.CropGrowthInfo.CropId),
                    new RequiredItem(gemBerrySeed.CropGrowthInfo.CropId),
                };
                MinimumRequiredItems = 2;
                Color = BundleColors.Blue;
                break;

            case BundleTypes.PantryDesert:
                Name          = Globals.GetTranslation("bundle-pantry-desert");
                RequiredItems = new List <RequiredItem>
                {
                    new RequiredItem((int)ObjectIndexes.IridiumOre, 5),
                    Globals.RNGGetRandomValueFromList(new List <RequiredItem>
                    {
                        new RequiredItem((int)ObjectIndexes.GoldenMask),
                        new RequiredItem((int)ObjectIndexes.GoldenRelic),
                    }),
                    Globals.RNGGetRandomValueFromList(RequiredItem.CreateList(FishItem.Get(Locations.Desert))),
                    Globals.RNGGetRandomValueFromList(RequiredItem.CreateList(ItemList.GetUniqueDesertForagables(), 1, 3)),
                    new RequiredItem((int)ObjectIndexes.StarfruitSeeds, 5)
                };
                MinimumRequiredItems = 4;
                Color = BundleColors.Yellow;
                break;

            case BundleTypes.PantryDessert:
                Name           = Globals.GetTranslation("bundle-pantry-dessert");
                potentialItems = new List <RequiredItem>
                {
                    new RequiredItem((int)ObjectIndexes.CranberryCandy),
                    new RequiredItem((int)ObjectIndexes.PlumPudding),
                    new RequiredItem((int)ObjectIndexes.PinkCake),
                    new RequiredItem((int)ObjectIndexes.PumpkinPie),
                    new RequiredItem((int)ObjectIndexes.RhubarbPie),
                    new RequiredItem((int)ObjectIndexes.Cookie),
                    new RequiredItem((int)ObjectIndexes.IceCream),
                    new RequiredItem((int)ObjectIndexes.MinersTreat),
                    new RequiredItem((int)ObjectIndexes.BlueberryTart),
                    new RequiredItem((int)ObjectIndexes.BlackberryCobbler),
                    new RequiredItem((int)ObjectIndexes.MapleBar),
                };
                RequiredItems        = Globals.RNGGetRandomValuesFromList(potentialItems, 8);
                MinimumRequiredItems = 4;
                Color = BundleColors.Cyan;
                break;

            case BundleTypes.PantryMexicanFood:
                Name          = Globals.GetTranslation("bundle-pantry-mexican-food");
                RequiredItems = new List <RequiredItem>
                {
                    new RequiredItem((int)ObjectIndexes.Tortilla),
                    new RequiredItem((int)ObjectIndexes.Corn, 1, 5),
                    new RequiredItem((int)ObjectIndexes.Tomato, 1, 5),
                    new RequiredItem((int)ObjectIndexes.HotPepper, 1, 5),
                    new RequiredItem((int)ObjectIndexes.FishTaco),
                    new RequiredItem((int)ObjectIndexes.Rice),
                    new RequiredItem((int)ObjectIndexes.Cheese),
                };
                MinimumRequiredItems = Range.GetRandomValue(4, 5);
                Color = BundleColors.Red;
                break;

            case BundleTypes.PantryColorBrown:
                Name           = Globals.GetTranslation("bundle-pantry-brown");
                potentialItems = RequiredItem.CreateList(new List <int>
                {
                    (int)ObjectIndexes.WildHorseradish,
                    (int)ObjectIndexes.CaveCarrot,
                    (int)ObjectIndexes.EarthCrystal,
                    (int)ObjectIndexes.Coconut,
                    (int)ObjectIndexes.Torch,
                    (int)ObjectIndexes.ChippedAmphora,
                    (int)ObjectIndexes.ChewingStick,
                    (int)ObjectIndexes.AncientSeed,
                    (int)ObjectIndexes.DwarvishHelm,
                    (int)ObjectIndexes.Driftwood,
                    (int)ObjectIndexes.BrownEgg,
                    (int)ObjectIndexes.LargeBrownEgg,
                    (int)ObjectIndexes.BakedFish,
                    (int)ObjectIndexes.ParsnipSoup,
                    (int)ObjectIndexes.CompleteBreakfast,
                    (int)ObjectIndexes.FriedMushroom,
                    (int)ObjectIndexes.CarpSurprise,
                    (int)ObjectIndexes.Hashbrowns,
                    (int)ObjectIndexes.Pancakes,
                    (int)ObjectIndexes.CrispyBass,
                    (int)ObjectIndexes.Bread,
                    (int)ObjectIndexes.TomKhaSoup,
                    (int)ObjectIndexes.ChocolateCake,
                    (int)ObjectIndexes.Cookie,
                    (int)ObjectIndexes.EggplantParmesan,
                    (int)ObjectIndexes.SurvivalBurger,
                    (int)ObjectIndexes.WheatFlour,
                    (int)ObjectIndexes.HardwoodFence,
                    (int)ObjectIndexes.Acorn,
                    (int)ObjectIndexes.PineCone,
                    (int)ObjectIndexes.WoodFence,
                    (int)ObjectIndexes.Gate,
                    (int)ObjectIndexes.WoodFloor,
                    (int)ObjectIndexes.Clay,
                    (int)ObjectIndexes.WeatheredFloor,
                    (int)ObjectIndexes.Wood,
                    (int)ObjectIndexes.Coffee,
                    (int)ObjectIndexes.CommonMushroom,
                    (int)ObjectIndexes.WoodPath,
                    (int)ObjectIndexes.Hazelnut,
                    (int)ObjectIndexes.Truffle,
                    (int)ObjectIndexes.Geode,
                    (int)ObjectIndexes.Mudstone,
                    (int)ObjectIndexes.AmphibianFossil,
                    (int)ObjectIndexes.PalmFossil,
                    (int)ObjectIndexes.PlumPudding,
                    (int)ObjectIndexes.RoastedHazelnuts,
                    (int)ObjectIndexes.Bruschetta,
                    (int)ObjectIndexes.QualitySprinkler,
                    (int)ObjectIndexes.PoppyseedMuffin,
                    (int)ObjectIndexes.RainTotem,
                    (int)ObjectIndexes.WarpTotemMountains,
                    (int)ObjectIndexes.CorkBobber,
                    (int)ObjectIndexes.PineTar,
                    (int)ObjectIndexes.MapleBar
                });
                RequiredItems        = Globals.RNGGetRandomValuesFromList(potentialItems, 8);
                MinimumRequiredItems = Range.GetRandomValue(3, 6);
                Color = BundleColors.Orange;
                break;

            case BundleTypes.PantryColorGreen:
                Name           = Globals.GetTranslation("bundle-pantry-green");
                potentialItems = RequiredItem.CreateList(new List <int>
                {
                    (int)ObjectIndexes.Emerald,
                    (int)ObjectIndexes.Jade,
                    (int)ObjectIndexes.CactusFruit,
                    (int)ObjectIndexes.DwarfScrollII,
                    (int)ObjectIndexes.StrangeDoll2,
                    (int)ObjectIndexes.Snail,
                    (int)ObjectIndexes.Seaweed,
                    (int)ObjectIndexes.GreenAlgae,
                    (int)ObjectIndexes.Salad,
                    (int)ObjectIndexes.BeanHotpot,
                    (int)ObjectIndexes.TroutSoup,
                    (int)ObjectIndexes.IceCream,
                    (int)ObjectIndexes.Stuffing,
                    (int)ObjectIndexes.FiddleheadFern,
                    (int)ObjectIndexes.GrassStarter,
                    (int)ObjectIndexes.Pickles,
                    (int)ObjectIndexes.Juice,
                    (int)ObjectIndexes.FieldSnack,
                    (int)ObjectIndexes.DuckFeather,
                    (int)ObjectIndexes.AlgaeSoup,
                    (int)ObjectIndexes.SlimeCharmerRing,
                    (int)ObjectIndexes.BurglarsRing,
                    (int)ObjectIndexes.JadeRing,
                    (int)ObjectIndexes.EmeraldRing,
                    (int)ObjectIndexes.Alamite,
                    (int)ObjectIndexes.Geminite,
                    (int)ObjectIndexes.Jamborite,
                    (int)ObjectIndexes.Malachite,
                    (int)ObjectIndexes.PetrifiedSlime,
                    (int)ObjectIndexes.OceanStone,
                    (int)ObjectIndexes.Coleslaw,
                    (int)ObjectIndexes.FiddleheadRisotto,
                    (int)ObjectIndexes.GreenSlimeEgg,
                    (int)ObjectIndexes.WarpTotemFarm,
                    (int)ObjectIndexes.OakResin,
                    (int)ObjectIndexes.FishStew,
                    (int)ObjectIndexes.Escargot,
                    (int)ObjectIndexes.Slime,
                    (int)ObjectIndexes.Fiber,
                    (int)ObjectIndexes.OilOfGarlic,
                    (int)ObjectIndexes.WildBait
                });
                RequiredItems        = Globals.RNGGetRandomValuesFromList(potentialItems, 8);
                MinimumRequiredItems = Range.GetRandomValue(3, 6);
                Color = BundleColors.Green;
                break;
            }
        }
        /// <summary>
        /// Calculates the seed price based on the seed growth info and price
        /// </summary>
        /// <param name="seed">The seed</param>
        /// <returns>
        /// Returns a value based on a random multiplier, regrowth days, and
        /// potential amount per harvest
        /// </returns>
        private static int CalculateCropPrice(SeedItem seed)
        {
            int seedPrice = seed.Price * 2;             // The amount we store here is half of what we want to base this off of
            CropGrowthInformation growthInfo = seed.CropGrowthInfo;

            double multiplier = 1;

            if (seedPrice < 31)
            {
                multiplier = Range.GetRandomValue(15, 40) / (double)10;
            }
            else if (seedPrice < 61)
            {
                multiplier = Range.GetRandomValue(15, 35) / (double)10;
            }
            else if (seedPrice < 91)
            {
                multiplier = Range.GetRandomValue(15, 30) / (double)10;
            }
            else if (seedPrice < 121)
            {
                multiplier = Range.GetRandomValue(15, 25) / (double)10;
            }
            else
            {
                multiplier = Range.GetRandomValue(15, 20) / (double)10;
            }

            double regrowthDaysMultiplier = 1;

            switch (growthInfo.DaysToRegrow)
            {
            case 1: regrowthDaysMultiplier = 0.3; break;

            case 2: regrowthDaysMultiplier = 0.4; break;

            case 3: regrowthDaysMultiplier = 0.5; break;

            case 4: regrowthDaysMultiplier = 0.6; break;

            case 5: regrowthDaysMultiplier = 0.7; break;

            case 6: regrowthDaysMultiplier = 0.8; break;

            case 7: regrowthDaysMultiplier = 0.9; break;

            default: regrowthDaysMultiplier = 1; break;
            }

            double amountPerHarvestMultiplier = 1;

            switch (growthInfo.ExtraCropInfo.MinExtra)
            {
            case 0: break;

            case 1: break;

            case 2: amountPerHarvestMultiplier = 0.6; break;

            case 3: amountPerHarvestMultiplier = 0.45; break;

            case 4: amountPerHarvestMultiplier = 0.3; break;

            default:
                Globals.ConsoleError($"Unexpected seed with more than 4 minimum extra crops: {seed.Id}");
                break;
            }
            if (growthInfo.ExtraCropInfo.CanGetExtraCrops && amountPerHarvestMultiplier == 1)
            {
                amountPerHarvestMultiplier = 0.9;
            }

            return((int)(seedPrice * multiplier * regrowthDaysMultiplier * amountPerHarvestMultiplier));
        }
        /// <summary>
        /// Gets a random file name that matches the crop growth image at the given position (fish excluded)
        /// Will remove the name found from the list
        /// </summary>
        /// <param name="position">The position</param>
        /// <returns>The selected file name</returns>
        protected override string GetRandomFileName(Point position)
        {
            ImageWidthInPx = 16;

            int    itemId       = PointsToItemIds[position];
            string fileName     = "";
            string subDirectory = "";

            if (BootData.AllBoots.Any(x => x.Id == itemId))
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(BootImages);

                if (string.IsNullOrEmpty(fileName))
                {
                    Globals.ConsoleWarn($"Could not find the boot image for id {itemId}; using default image instead.");
                    return(null);
                }

                return(fileName);
            }

            Item item = ItemList.Items[itemId];

            if (item.Id == (int)ObjectIndexes.CherrySapling)
            {
                ImageWidthInPx = 96;
                return($"{ImageDirectory}/fruitTreeSprites.png");
            }

            if (item.IsFish)
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(FishImages);

                if (string.IsNullOrEmpty(fileName))
                {
                    Globals.ConsoleWarn($"Could not find the fish image for {item.Name}; using default image instead.");
                    return(null);
                }

                return(fileName);
            }

            int cropId = item.Id;

            if (item.IsCrop || item.Id == (int)ObjectIndexes.CoffeeBean)
            {
                subDirectory = "/Crops";
            }

            else if (item.IsSeed)
            {
                SeedItem seedItem = (SeedItem)item;
                cropId       = seedItem.CropGrowthInfo.CropId;
                subDirectory = "/Seeds";
            }

            if (item.IsFlower)
            {
                subDirectory = "/Flowers";

                CropItem cropItem = (CropItem)item;
                if (cropItem.MatchingSeedItem.CropGrowthInfo.TintColorInfo.HasTint)
                {
                    ImageWidthInPx = 32;                     // Flower images include the stem and the top if they have tint
                }
            }

            if (!CropIdsToImageNames.TryGetValue(cropId, out fileName))
            {
                Globals.ConsoleWarn($"Could not find the matching image for {item.Name}; using default image instead.");
                return(null);
            }

            return($"{ImageDirectory}{subDirectory}/{fileName}");
        }