From 53fb1a7d84194eb1945ea1604780fe8f64085e32 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:02:25 +0000 Subject: [PATCH 1/4] Initial plan From c5c8da5d87c7d3f3610ccd517dbbee9d31453c10 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:13:42 +0000 Subject: [PATCH 2/4] Implement soil testing feature for fields - Phase 1 & 2 complete Co-authored-by: SpaceTrucker2196 <641430+SpaceTrucker2196@users.noreply.github.com> --- DeepLevel/CityMapGenerator.swift | 7 + DeepLevel/Entity.swift | 46 +++++- DeepLevel/GameScene.swift | 73 ++++++++- DeepLevel/ItemDatabase.swift | 11 +- DeepLevel/TileType.swift | 197 ++++++++++++++++++++++++- DeepLevelTests/DeepLevelTests.swift | 149 +++++++++++++++++++ Docs/DeepLevel.docc/Getting-Started.md | 28 ++++ 7 files changed, 506 insertions(+), 5 deletions(-) diff --git a/DeepLevel/CityMapGenerator.swift b/DeepLevel/CityMapGenerator.swift index 823cfae..2b9e51b 100644 --- a/DeepLevel/CityMapGenerator.swift +++ b/DeepLevel/CityMapGenerator.swift @@ -153,9 +153,16 @@ final class CityMapGenerator: DungeonGenerating { tiles[idx].kind = actualTileKind tiles[idx].scale = scaleFactor + // Add soil properties for park tiles + if districtType == .park { + tiles[idx].soilProperties = SoilProperties() + } + if districtType == .park && Double.random(in: 0..<1, using: &rng) < 0.5 { tiles[idx].kind = .hidingArea tiles[idx].scale = 1.0 + // Hiding areas in parks should also have soil properties + tiles[idx].soilProperties = SoilProperties() } } } diff --git a/DeepLevel/Entity.swift b/DeepLevel/Entity.swift index a0094cc..ad251b4 100644 --- a/DeepLevel/Entity.swift +++ b/DeepLevel/Entity.swift @@ -121,6 +121,7 @@ final class Charmed: Entity { final class Player: Entity { var inventory: [StoredItem] = [] private var lastHealTime: TimeInterval = 0 + var soilTestResults: [SoilTestResult] = [] init(gridX: Int, gridY: Int, tileSize: CGFloat, scale: CGFloat = 1.0) { super.init(kind: .player, @@ -146,9 +147,50 @@ final class Player: Entity { return CACurrentMediaTime() - lastHealTime < 10.0 // 10 seconds } + /// Check if player has any soil testing equipment + func hasSoilTestingEquipment() -> Bool { + return inventory.contains { item in + ["pH Test Kit", "Moisture Meter", "Soil Thermometer", "Soil Probe", "NPK Test Kit"].contains(item.title) + } + } + + /// Get available soil testing equipment + func availableSoilTestingEquipment() -> [StoredItem] { + return inventory.filter { item in + ["pH Test Kit", "Moisture Meter", "Soil Thermometer", "Soil Probe", "NPK Test Kit"].contains(item.title) + } + } + + /// Perform a soil test using the first available equipment + func performSoilTest(at location: (Int, Int), soilProperties: SoilProperties) -> SoilTestResult? { + guard let equipment = availableSoilTestingEquipment().first else { + return nil + } + + let result = SoilTestResult(location: location, equipment: equipment.title, soilProperties: soilProperties) + soilTestResults.append(result) + return result + } + + /// Perform a soil test using specific equipment + func performSoilTest(at location: (Int, Int), soilProperties: SoilProperties, using equipmentName: String) -> SoilTestResult? { + guard inventory.contains(where: { $0.title == equipmentName }) else { + return nil + } + + let result = SoilTestResult(location: location, equipment: equipmentName, soilProperties: soilProperties) + soilTestResults.append(result) + return result + } + private func initializeStartingInventory(tileSize: CGFloat) { - let startingItemDefs = ItemDatabase.randomItems(count: 3) - for itemDef in startingItemDefs { + // Start with 2 random items and 1 soil testing equipment + let randomItems = ItemDatabase.randomItems(count: 2) + let soilTestingItems = ItemDatabase.randomItems(from: .soilTesting, count: 1) + + let allStartingItems = randomItems + soilTestingItems + + for itemDef in allStartingItems { let item = StoredItem(name: itemDef.name, description: itemDef.description, gridX: gridX, // Items start at player position conceptually diff --git a/DeepLevel/GameScene.swift b/DeepLevel/GameScene.swift index 3a7cacd..fc29dd0 100644 --- a/DeepLevel/GameScene.swift +++ b/DeepLevel/GameScene.swift @@ -894,10 +894,18 @@ final class GameScene: SKScene { y: CGFloat(player.gridY) * tileSize + tileSize/2 ) - // Check if tapping on or very close to the player - if so, stop movement + // Check if tapping on or very close to the player - if so, stop movement or perform soil test let distanceToPlayer = hypot(location.x - playerScreenPos.x, location.y - playerScreenPos.y) if distanceToPlayer < tileSize { continuousMovementDir = (0, 0) + + // Check if player can perform soil test at current location + if let map = map { + let currentTile = map.tiles[map.index(x: player.gridX, y: player.gridY)] + if currentTile.canTestSoil && player.hasSoilTestingEquipment() { + performSoilTest(player: player, tile: currentTile, location: (player.gridX, player.gridY)) + } + } return } @@ -932,6 +940,69 @@ final class GameScene: SKScene { camera.run(zoomAction) } + // MARK: - Soil Testing + + /// Perform a soil test at the player's current location + private func performSoilTest(player: Player, tile: Tile, location: (Int, Int)) { + guard let soilProperties = tile.soilProperties else { return } + + // Perform the soil test using the first available equipment + if let result = player.performSoilTest(at: location, soilProperties: soilProperties) { + // Mark the soil as tested + if let map = map { + var mutableTile = map.tiles[map.index(x: location.0, y: location.1)] + if var properties = mutableTile.soilProperties { + properties.hasBeenTested = true + mutableTile.soilProperties = properties + // Update the tile in the map + map.tiles[map.index(x: location.0, y: location.1)] = mutableTile + } + } + + // Display the soil test result to the player + showSoilTestResult(result) + + if debugLogging { + print("[GameScene] Soil test performed at (\(location.0), \(location.1)) using \(result.equipmentUsed)") + print("[GameScene] Result: \(result.assessment)") + } + } + } + + /// Display soil test results to the player + private func showSoilTestResult(_ result: SoilTestResult) { + // Create a temporary label to show the test result + let resultLabel = SKLabelNode(fontNamed: "Arial") + resultLabel.text = result.assessment + resultLabel.fontSize = 16 + resultLabel.fontColor = .white + resultLabel.position = CGPoint(x: 0, y: 100) // Position above player + resultLabel.zPosition = 1000 // Ensure it's on top + + // Add background for better readability + let background = SKShapeNode(rectOf: CGSize(width: resultLabel.frame.width + 20, height: 30)) + background.fillColor = SKColor.black.withAlphaComponent(0.8) + background.strokeColor = .clear + background.position = resultLabel.position + background.zPosition = 999 + + // Add to camera node so it stays in view + if let camera = camNode { + camera.addChild(background) + camera.addChild(resultLabel) + + // Animate the label appearance and removal + let fadeIn = SKAction.fadeAlpha(to: 1.0, duration: 0.3) + let wait = SKAction.wait(forDuration: 3.0) + let fadeOut = SKAction.fadeAlpha(to: 0.0, duration: 0.5) + let remove = SKAction.removeFromParent() + let sequence = SKAction.sequence([fadeIn, wait, fadeOut, remove]) + + background.run(sequence) + resultLabel.run(sequence) + } + } + // ., } diff --git a/DeepLevel/ItemDatabase.swift b/DeepLevel/ItemDatabase.swift index c7b9502..c899053 100644 --- a/DeepLevel/ItemDatabase.swift +++ b/DeepLevel/ItemDatabase.swift @@ -13,6 +13,7 @@ struct ItemDatabase { case useful case food case curious + case soilTesting } /// Definition of an item with its properties. @@ -70,7 +71,15 @@ struct ItemDatabase { ItemDefinition(name: "Marble", description: "A single glass marble, green with swirls.", category: .curious, value: 8), ItemDefinition(name: "Lottery Ticket", description: "A scratched lottery ticket. Looks like a loser.", category: .curious, value: 1), ItemDefinition(name: "USB Drive", description: "A tiny USB drive. Wonder what's on it?", category: .curious, value: 20), - ItemDefinition(name: "Toy Soldier", description: "A small plastic soldier missing his rifle.", category: .curious, value: 7) + ItemDefinition(name: "Toy Soldier", description: "A small plastic soldier missing his rifle.", category: .curious, value: 7), + + // Soil Testing Equipment + ItemDefinition(name: "pH Test Kit", description: "A portable soil pH testing kit with color strips.", category: .soilTesting, value: 25), + ItemDefinition(name: "Soil Probe", description: "A metal probe for testing soil compaction and depth.", category: .soilTesting, value: 30), + ItemDefinition(name: "Moisture Meter", description: "Digital device for measuring soil moisture content.", category: .soilTesting, value: 35), + ItemDefinition(name: "Soil Thermometer", description: "Specialized thermometer for measuring soil temperature.", category: .soilTesting, value: 20), + ItemDefinition(name: "NPK Test Kit", description: "Tests for nitrogen, phosphorus, and potassium levels.", category: .soilTesting, value: 40), + ItemDefinition(name: "Soil Sample Bag", description: "Sterile bag for collecting soil samples for analysis.", category: .soilTesting, value: 5) ] /// Get a random item from the database. diff --git a/DeepLevel/TileType.swift b/DeepLevel/TileType.swift index 349d0b7..3541b83 100644 --- a/DeepLevel/TileType.swift +++ b/DeepLevel/TileType.swift @@ -1,5 +1,78 @@ import SpriteKit +/// Represents soil quality properties for testable tiles. +/// +/// Contains measurements and characteristics that can be discovered through soil testing. +/// Values are generated randomly but remain consistent for each tile location. +/// +/// - Since: 1.0.0 +struct SoilProperties { + /// Soil pH level (1.0-14.0, with 7.0 being neutral) + let pH: Float + + /// Moisture content percentage (0.0-100.0) + let moisture: Float + + /// Soil temperature in Celsius (-10.0 to 40.0) + let temperature: Float + + /// Nitrogen level (0.0-100.0) + let nitrogen: Float + + /// Phosphorus level (0.0-100.0) + let phosphorus: Float + + /// Potassium level (0.0-100.0) + let potassium: Float + + /// Soil compaction level (0.0-100.0, higher = more compacted) + let compaction: Float + + /// Has this soil been tested by the player? + var hasBeenTested: Bool = false + + /// Initialize with random but realistic soil values + init() { + // Generate realistic soil values + self.pH = Float.random(in: 4.5...8.5) + self.moisture = Float.random(in: 10.0...80.0) + self.temperature = Float.random(in: 5.0...25.0) + self.nitrogen = Float.random(in: 5.0...95.0) + self.phosphorus = Float.random(in: 3.0...75.0) + self.potassium = Float.random(in: 8.0...85.0) + self.compaction = Float.random(in: 15.0...85.0) + } + + /// Initialize with specific values (for testing) + init(pH: Float, moisture: Float, temperature: Float, nitrogen: Float, phosphorus: Float, potassium: Float, compaction: Float) { + self.pH = pH + self.moisture = moisture + self.temperature = temperature + self.nitrogen = nitrogen + self.phosphorus = phosphorus + self.potassium = potassium + self.compaction = compaction + } + + /// Get soil quality description based on values + var qualityDescription: String { + let avgNutrient = (nitrogen + phosphorus + potassium) / 3.0 + let pHGood = pH >= 6.0 && pH <= 7.5 + let moistureGood = moisture >= 25.0 && moisture <= 65.0 + let compactionGood = compaction <= 50.0 + + if avgNutrient > 70.0 && pHGood && moistureGood && compactionGood { + return "Excellent soil quality - ideal for most plants!" + } else if avgNutrient > 50.0 && pHGood && moistureGood { + return "Good soil quality - suitable for gardening." + } else if avgNutrient > 30.0 { + return "Fair soil quality - may need amendments." + } else { + return "Poor soil quality - requires significant improvement." + } + } +} + /// Represents different types of tiles that can exist in a dungeon map. /// /// Defines the basic tile categories used for dungeon generation and rendering. @@ -79,7 +152,7 @@ enum TileKind: UInt8 { /// Represents a single tile in the dungeon map with its properties and state. /// /// Contains all information needed to render and interact with a single tile position, -/// including its type, visibility state, visual variation, and scaling information. +/// including its type, visibility state, visual variation, scaling information, and soil properties. /// /// - Since: 1.0.0 struct Tile { @@ -101,6 +174,9 @@ struct Tile { /// Scale factor for the tile (1.0 = normal size, 2.0 = double size). var scale: CGFloat = 1.0 + /// Soil properties for park tiles that can be tested + var soilProperties: SoilProperties? + /// Indicates whether this tile blocks entity movement. /// /// - Returns: `true` if the tile prevents entities from moving through it. @@ -150,4 +226,123 @@ struct Tile { default: return false } } + + /// Indicates whether this tile can be tested for soil properties. + /// + /// - Returns: `true` if the tile represents an area where soil testing makes sense. + var canTestSoil: Bool { + switch kind { + case .park, .hidingArea: return soilProperties != nil + default: return false + } + } +} + +/// Represents the results of a soil test performed by the player. +/// +/// Contains the measured values and analysis based on the player's available testing equipment. +/// Different equipment reveals different aspects of soil composition. +/// +/// - Since: 1.0.0 +struct SoilTestResult { + /// The location where the test was performed + let gridX: Int + let gridY: Int + + /// Which soil testing equipment was used + let equipmentUsed: String + + /// The measured/revealed properties based on equipment capabilities + var measuredpH: Float? + var measuredMoisture: Float? + var measuredTemperature: Float? + var measuredNitrogen: Float? + var measuredPhosphorus: Float? + var measuredPotassium: Float? + var measuredCompaction: Float? + + /// Overall assessment based on available measurements + var assessment: String + + /// When the test was performed + let timestamp: Date + + init(location: (Int, Int), equipment: String, soilProperties: SoilProperties) { + self.gridX = location.0 + self.gridY = location.1 + self.equipmentUsed = equipment + self.timestamp = Date() + + // Different equipment reveals different properties + switch equipment { + case "pH Test Kit": + self.measuredpH = soilProperties.pH + self.assessment = "pH Level: \(String(format: "%.1f", soilProperties.pH)) - \(SoilTestResult.pHDescription(soilProperties.pH))" + + case "Moisture Meter": + self.measuredMoisture = soilProperties.moisture + self.assessment = "Moisture: \(String(format: "%.1f", soilProperties.moisture))% - \(SoilTestResult.moistureDescription(soilProperties.moisture))" + + case "Soil Thermometer": + self.measuredTemperature = soilProperties.temperature + self.assessment = "Temperature: \(String(format: "%.1f", soilProperties.temperature))°C - \(SoilTestResult.temperatureDescription(soilProperties.temperature))" + + case "Soil Probe": + self.measuredCompaction = soilProperties.compaction + self.assessment = "Compaction: \(String(format: "%.1f", soilProperties.compaction))% - \(SoilTestResult.compactionDescription(soilProperties.compaction))" + + case "NPK Test Kit": + self.measuredNitrogen = soilProperties.nitrogen + self.measuredPhosphorus = soilProperties.phosphorus + self.measuredPotassium = soilProperties.potassium + let avgNPK = (soilProperties.nitrogen + soilProperties.phosphorus + soilProperties.potassium) / 3.0 + self.assessment = "NPK - N:\(String(format: "%.0f", soilProperties.nitrogen)) P:\(String(format: "%.0f", soilProperties.phosphorus)) K:\(String(format: "%.0f", soilProperties.potassium)) - \(SoilTestResult.npkDescription(avgNPK))" + + default: + self.assessment = "Basic soil analysis completed." + } + } + + private static func pHDescription(_ pH: Float) -> String { + switch pH { + case 0.0..<6.0: return "Acidic" + case 6.0..<7.5: return "Ideal for most plants" + case 7.5..<8.5: return "Slightly alkaline" + default: return "Highly alkaline" + } + } + + private static func moistureDescription(_ moisture: Float) -> String { + switch moisture { + case 0.0..<20.0: return "Very dry" + case 20.0..<40.0: return "Dry" + case 40.0..<70.0: return "Good moisture" + default: return "Very wet" + } + } + + private static func temperatureDescription(_ temp: Float) -> String { + switch temp { + case ..<10.0: return "Cold" + case 10.0..<20.0: return "Cool" + case 20.0..<30.0: return "Warm" + default: return "Hot" + } + } + + private static func compactionDescription(_ compaction: Float) -> String { + switch compaction { + case 0.0..<30.0: return "Loose, well-aerated" + case 30.0..<60.0: return "Moderately compact" + default: return "Highly compacted" + } + } + + private static func npkDescription(_ avg: Float) -> String { + switch avg { + case 0.0..<30.0: return "Low nutrients" + case 30.0..<60.0: return "Moderate nutrients" + default: return "High nutrients" + } + } } diff --git a/DeepLevelTests/DeepLevelTests.swift b/DeepLevelTests/DeepLevelTests.swift index b1fa374..d957639 100644 --- a/DeepLevelTests/DeepLevelTests.swift +++ b/DeepLevelTests/DeepLevelTests.swift @@ -1324,5 +1324,154 @@ struct DeepLevelTests { #expect(fovRadius < 5, "FOV radius should be optimized") #expect(fovRadius >= 3, "FOV radius should provide reasonable visibility") } + + /// Tests soil testing functionality for park tiles. + /// + /// Verifies that soil properties are generated for park tiles and that + /// players can perform soil tests using appropriate equipment. + /// + /// - Throws: Any errors encountered during test execution + @Test func testSoilTestingFunctionality() async throws { + // Create a city map with parks to test soil functionality + var config = DungeonConfig() + config.width = 30 + config.height = 30 + config.algorithm = .cityMap + config.parkFrequency = 1.0 // Ensure we get parks + + let generator = CityMapGenerator() + var rng = SystemRandomNumberGenerator() + let map = generator.generate(config: config, rng: &rng) + + // Find a park tile with soil properties + var parkTileFound = false + var testLocation: (Int, Int)? = nil + + for y in 0..= 4.5 && $0 <= 8.5 }, "pH should be in realistic range") + + // Test moisture range (should be between 10.0 and 80.0) + let moistureValues = soilSamples.map { $0.moisture } + #expect(moistureValues.allSatisfy { $0 >= 10.0 && $0 <= 80.0 }, "Moisture should be in realistic range") + + // Test temperature range (should be between 5.0 and 25.0) + let temperatureValues = soilSamples.map { $0.temperature } + #expect(temperatureValues.allSatisfy { $0 >= 5.0 && $0 <= 25.0 }, "Temperature should be in realistic range") + + // Test that values are actually randomized (not all the same) + let uniquepH = Set(pHValues.map { Int($0 * 10) }) // Round to 1 decimal place for comparison + #expect(uniquepH.count > 1, "pH values should be randomized") + + // Test quality description generation + let qualityDescriptions = soilSamples.map { $0.qualityDescription } + let uniqueDescriptions = Set(qualityDescriptions) + #expect(uniqueDescriptions.count > 1, "Should generate different quality descriptions") + + // Test specific soil property initialization + let specificSoil = SoilProperties(pH: 7.0, moisture: 50.0, temperature: 20.0, + nitrogen: 60.0, phosphorus: 40.0, potassium: 80.0, + compaction: 30.0) + #expect(specificSoil.pH == 7.0) + #expect(specificSoil.moisture == 50.0) + #expect(specificSoil.qualityDescription.contains("Good")) + } + + /// Tests soil testing equipment functionality in ItemDatabase. + /// + /// Verifies that soil testing items are properly categorized and available + /// in the item database with appropriate properties. + /// + /// - Throws: Any errors encountered during test execution + @Test func testSoilTestingEquipment() async throws { + // Get all soil testing items + let soilTestingItems = ItemDatabase.randomItems(from: .soilTesting, count: 10) + + // Should return all available soil testing items (we added 6) + #expect(soilTestingItems.count >= 5, "Should have multiple soil testing items available") + + // Verify soil testing items have appropriate properties + for item in soilTestingItems { + #expect(item.category == .soilTesting) + #expect(item.value > 0, "Soil testing equipment should have value") + #expect(!item.name.isEmpty) + #expect(!item.description.isEmpty) + + // Verify specific equipment names + let validEquipmentNames = ["pH Test Kit", "Soil Probe", "Moisture Meter", + "Soil Thermometer", "NPK Test Kit", "Soil Sample Bag"] + #expect(validEquipmentNames.contains(item.name), "Should be valid soil testing equipment") + } + + // Test that players can identify soil testing equipment + let player = Player(gridX: 0, gridY: 0, tileSize: 32.0) + let hasEquipment = player.hasSoilTestingEquipment() + + // Player should start with some soil testing equipment + #expect(hasEquipment, "Player should start with soil testing equipment") + + let availableEquipment = player.availableSoilTestingEquipment() + #expect(availableEquipment.count > 0, "Player should have soil testing equipment available") + } } + diff --git a/Docs/DeepLevel.docc/Getting-Started.md b/Docs/DeepLevel.docc/Getting-Started.md index 87070a8..16a9fa7 100644 --- a/Docs/DeepLevel.docc/Getting-Started.md +++ b/Docs/DeepLevel.docc/Getting-Started.md @@ -87,6 +87,34 @@ if tile.explored { } ``` +### Soil Testing Feature + +DeepLevel includes a soil testing system for park areas that allows players to analyze soil quality: + +```swift +// Players automatically start with soil testing equipment +let player = Player(gridX: x, gridY: y, tileSize: 32.0) + +// Check if player has soil testing equipment +if player.hasSoilTestingEquipment() { + print("Player has soil testing equipment available") +} + +// Park tiles automatically include soil properties +let tile = map.tiles[map.index(x: x, y: y)] +if tile.canTestSoil { + // This tile can be tested (parks and hiding areas in parks) + if let soilProperties = tile.soilProperties { + // Perform soil test using available equipment + if let result = player.performSoilTest(at: (x, y), soilProperties: soilProperties) { + print("Soil test result: \(result.assessment)") + } + } +} +``` + +Players can tap on themselves while standing in park areas to perform soil tests using their available equipment. Different equipment reveals different soil properties like pH, moisture, nutrients, and compaction. + ## Next Steps - Explore different generation algorithms in From 79b686001cb304604f7c5bf623f5a275e9f7f240 Mon Sep 17 00:00:00 2001 From: Jeff Kunzelman Date: Mon, 25 Aug 2025 13:57:54 -0500 Subject: [PATCH 3/4] Update DeepLevel/Entity.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- DeepLevel/Entity.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/DeepLevel/Entity.swift b/DeepLevel/Entity.swift index ad251b4..cba0a71 100644 --- a/DeepLevel/Entity.swift +++ b/DeepLevel/Entity.swift @@ -157,7 +157,14 @@ final class Player: Entity { /// Get available soil testing equipment func availableSoilTestingEquipment() -> [StoredItem] { return inventory.filter { item in - ["pH Test Kit", "Moisture Meter", "Soil Thermometer", "Soil Probe", "NPK Test Kit"].contains(item.title) + Player.soilTestingEquipmentNames.contains(item.title) + } + } + + /// Get available soil testing equipment + func availableSoilTestingEquipment() -> [StoredItem] { + return inventory.filter { item in + Player.soilTestingEquipmentNames.contains(item.title) } } From 499de75cc0d179564471748d053da1252693a99f Mon Sep 17 00:00:00 2001 From: Jeff Kunzelman Date: Mon, 25 Aug 2025 13:58:18 -0500 Subject: [PATCH 4/4] Update DeepLevelTests/DeepLevelTests.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- DeepLevelTests/DeepLevelTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DeepLevelTests/DeepLevelTests.swift b/DeepLevelTests/DeepLevelTests.swift index d957639..0e784e4 100644 --- a/DeepLevelTests/DeepLevelTests.swift +++ b/DeepLevelTests/DeepLevelTests.swift @@ -1458,7 +1458,7 @@ struct DeepLevelTests { // Verify specific equipment names let validEquipmentNames = ["pH Test Kit", "Soil Probe", "Moisture Meter", - "Soil Thermometer", "NPK Test Kit", "Soil Sample Bag"] + let validEquipmentNames = ItemDatabase.items(for: .soilTesting).map { $0.name } #expect(validEquipmentNames.contains(item.name), "Should be valid soil testing equipment") }