public bool ValidateDungeons(Command command) { bool success = true; string result= SuccessMessages.GENERAL_SUCCESS; RoomTemplateSet roomTemplateSet = new RoomTemplateSet(); MobTypeSet mobTypeSet = new MobTypeSet(); MobSpawnTableSet mobSpawnTableSet = new MobSpawnTableSet(); int game_id_min = 0; int game_id_max = 100000; // Int32.MaxValue; This will take ~100 days to finish all 2 billion dungeons string connection_string = ""; string dumpGeometryPath = ""; if (command.HasArgumentWithName("C")) { connection_string = command.GetTypedArgumentByName<CommandArgument_String>("C").ArgumentValue; } else { _logger.WriteLine("DungeonValidator: Missing expected connection string parameter"); success = false; } if (command.HasArgumentWithName("G")) { game_id_min = command.GetTypedArgumentByName<CommandArgument_Int32>("G").ArgumentValue; game_id_max = game_id_min; } else { _logger.WriteLine("DungeonValidator: No game id given, evaluating all possible game ids"); } if (game_id_min == game_id_max && command.HasArgumentWithName("D")) { dumpGeometryPath = command.GetTypedArgumentByName<CommandArgument_String>("D").ArgumentValue; } _logger.WriteLine("Validating layouts for game_ids {0} to {1}", game_id_min, game_id_max); // Get the room templates from the DB if (success && !roomTemplateSet.Initialize(connection_string, out result)) { _logger.WriteLine(string.Format("DungeonValidator: Failed to load the room templates from the DB: {0}", result)); success = false; } // Get the mob type set from the DB if (success && !mobTypeSet.Initialize(connection_string, out result)) { _logger.WriteLine(string.Format("DungeonValidator: Failed to load the mob types from the DB: {0}", result)); success = false; } // Get the mob spawn templates from the DB if (success && !mobSpawnTableSet.Initialize(connection_string, mobTypeSet, out result)) { _logger.WriteLine(string.Format("DungeonValidator: Failed to load the mob spawn tables from the DB: {0}", result)); success = false; } if (success) { DateTime startTime = DateTime.Now; // Test all possible world size configurations for each desired game id WorldTemplate[] worldTemplates = new WorldTemplate[] { new WorldTemplate(GameConstants.eDungeonSize.small, GameConstants.eDungeonDifficulty.normal), new WorldTemplate(GameConstants.eDungeonSize.medium, GameConstants.eDungeonDifficulty.normal), new WorldTemplate(GameConstants.eDungeonSize.large, GameConstants.eDungeonDifficulty.normal), }; for (int game_id = game_id_min; success && game_id <= game_id_max; ++game_id) { foreach (WorldTemplate worldTemplate in worldTemplates) { DungeonLayout layout = new DungeonLayout(game_id, worldTemplate, roomTemplateSet, mobSpawnTableSet); // Create the initial set of rooms for the world if (!layout.BuildRoomLayout(out result)) { _logger.WriteLine( string.Format("DungeonValidator: Failed to generate dungeon layout, game_id:{0}, size:{1}", game_id, worldTemplate.dungeon_size)); _logger.WriteLine(result); success = false; } // Verify that this is a valid dungeon if (success) { Dictionary<int, Portal> portalIdToPortalMap = BuildPortalIdMap(layout); // Verify that all portals are connected correctly success &= VerifyRoomPortals(layout, portalIdToPortalMap); // Verify that every room is accessible to every other room success &= VerifyRoomAccessibility(layout, portalIdToPortalMap); // Verify monster spawners success &= VerifyMobSpawners(layout); } // Dump the generated layout to a .obj file if (dumpGeometryPath.Length > 0) { DumpLayoutGeometry(dumpGeometryPath, layout); } } if (game_id_max > game_id_min) { if ((game_id % 1000) == 0) { TimeSpan elapsed = DateTime.Now.Subtract(startTime); int percent_complete = 100 * (game_id - game_id_min) / (game_id_max - game_id_min); _logger.Write("\r[{0:c}] {1}/{2} {3}%", elapsed, game_id-game_id_min, game_id_max-game_id_min, percent_complete); } } } // Write out a new line after the timing info _logger.WriteLine(); } return success; }
public void ParseRoomTemplates( AsyncRPGDataContext db_context, string template_path) { MobTypeSet mobTypeSet = new MobTypeSet(); MobSpawnTableSet mobSpawnTableSet = new MobSpawnTableSet(); // Clear out any existing room templates db_context.ExecuteCommand("DELETE FROM room_templates"); // Get the mob type set from the DB mobTypeSet.Initialize(db_context); // Get the mob spawn templates from the DB mobSpawnTableSet.Initialize(db_context, mobTypeSet); // Read in each XML file and save it into the room templates table string[] templateFiles = Directory.GetFiles(template_path, "*.oel"); if (templateFiles == null || templateFiles.Length == 0) { throw new Exception("RoomTemplateParser: No room template files (*.oel) found in directory: " + template_path); } { Dictionary<TypedFlags<MathConstants.eSignedDirection>, int> portalLayoutCounts = new Dictionary<TypedFlags<MathConstants.eSignedDirection>, int>(); bool anyRoomParsingErrors = false; foreach (string templateFile in templateFiles) { string templateName = Path.GetFileNameWithoutExtension(templateFile); RoomTemplate roomTemplate = null; byte[] compressedNavCells = null; byte[] compressedPVS = null; // Parse the XML template from the file XmlDocument doc = new XmlDocument(); doc.Load(templateFile); // Parse the room template xml into a room template object roomTemplate = new RoomTemplate(templateName, doc); // Keep track of all of the unique portal layouts we encounter if (portalLayoutCounts.ContainsKey(roomTemplate.PortalRoomSideBitmask)) { portalLayoutCounts[roomTemplate.PortalRoomSideBitmask] += 1; } else { portalLayoutCounts.Add(roomTemplate.PortalRoomSideBitmask, 1); } // Extract the nav-mesh and visibility data in compressed form to save into the DB roomTemplate.NavMeshTemplate.ToCompressedData(out compressedNavCells, out compressedPVS); // Remove everything from the template XML that we wont care about at runtime RemoveXmlNodeByXPath(doc, "/level/Floor"); RemoveXmlNodeByXPath(doc, "/level/Walls"); RemoveXmlNodeByXPath(doc, "/level/BackgroundObjects"); RemoveXmlNodeByXPath(doc, "/level/ForegroundObjects"); RemoveXmlNodeByXPath(doc, "/level/NavMesh"); if (ValidateRoomTemplate( templateName, roomTemplate, mobSpawnTableSet, compressedNavCells, compressedPVS)) { // Save the XML back into string StringWriter stringWriter = new StringWriter(); XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter); doc.WriteTo(xmlWriter); RoomTemplates dbRoomTemplate = new RoomTemplates { Name = templateName, XML = stringWriter.ToString(), CompressedNavMesh = compressedNavCells, CompressedVisibility = compressedPVS }; db_context.RoomTemplates.InsertOnSubmit(dbRoomTemplate); db_context.SubmitChanges(); _logger.LogInfo("RoomTemplateParser: Added Room Template:"); _logger.LogInfo(templateFile); } else { anyRoomParsingErrors = true; } } // Verify all possible door-side combinations are represented in the template file set if (portalLayoutCounts.Keys.Count < k_expectedRoomLayouts.Length) { foreach (TypedFlags<MathConstants.eSignedDirection> expectedLayout in k_expectedRoomLayouts) { if (!portalLayoutCounts.ContainsKey(expectedLayout)) { _logger.LogError( string.Format( "RoomTemplateParser: Missing expected room layout: {0}{1}{2}{3}{4}{5}", expectedLayout.Test(MathConstants.eSignedDirection.positive_x) ? "X+" : "", expectedLayout.Test(MathConstants.eSignedDirection.negative_x) ? "X-" : "", expectedLayout.Test(MathConstants.eSignedDirection.positive_y) ? "Y+" : "", expectedLayout.Test(MathConstants.eSignedDirection.negative_y) ? "Y-" : "", expectedLayout.Test(MathConstants.eSignedDirection.positive_z) ? "Z+" : "", expectedLayout.Test(MathConstants.eSignedDirection.negative_z) ? "Z-" : "")); anyRoomParsingErrors = true; } } } if (anyRoomParsingErrors) { throw new Exception("RoomTemplateParser: Failed to parse all room templates"); } } }