public ISeedData GenerateSeed(IDictionary <string, string> options, string seed, CancellationToken cancellationToken) { int randoSeed; if (string.IsNullOrEmpty(seed)) { randoSeed = System.Security.Cryptography.RandomNumberGenerator.GetInt32(0, int.MaxValue); seed = randoSeed.ToString(); } else { randoSeed = int.Parse(seed); /* The Random ctor takes the absolute value of a negative seed. * This is an non-obvious behavior so we treat a negative value * as out of range. */ if (randoSeed < 0) { throw new ArgumentOutOfRangeException("Expected the seed option value to be an integer value in the range [0, 2147483647]"); } } var randoRnd = new Random(randoSeed); var config = RandomizerOptions.Parse(options); /* FIXME: Just here to semi-obfuscate race seeds until a better solution is in place */ if (config.Race) { randoRnd = new Random(randoRnd.Next()); } var worlds = new List <World>(); if (config.SingleWorld) { worlds.Add(new World(config, "Player", 0, new HexGuid())); } else { var players = options.ContainsKey("players") ? int.Parse(options["players"]) : 1; for (var p = 0; p < players; p++) { var found = options.TryGetValue($"player-{p}", out var player); if (!found) { throw new ArgumentException($"No name provided for player {p + 1}"); } if (!legalCharacters.IsMatch(player)) { throw new ArgumentException($"No alphanumeric characters found in name for player {p + 1}"); } player = CleanPlayerName(player); worlds.Add(new World(config, player, p, new HexGuid())); } } var filler = new Filler(worlds, config, randoRnd, cancellationToken); filler.Fill(); var seedData = new SeedData { Guid = new HexGuid(), Seed = seed, Game = Name, Mode = config.GameMode.ToLowerString(), Logic = $"{config.SMLogic.ToLowerString()}+{config.Z3Logic.ToLowerString()}", Playthrough = config.Race ? new List <Dictionary <string, string> >() : Playthrough.Generate(worlds, config), Worlds = new List <IWorldData>(), }; /* Make sure RNG is the same when applying patches to the ROM to have consistent RNG for seed identifer etc */ int patchSeed = randoRnd.Next(); foreach (var world in worlds) { var patchRnd = new Random(patchSeed); var patch = new Patch(world, worlds, seedData.Guid, config.Race ? 0 : randoSeed, patchRnd); var worldData = new WorldData { Id = world.Id, Guid = world.Guid, Player = world.Player, Patches = patch.Create(config), Locations = world.Locations .Select(l => new LocationData() { LocationId = l.Id, ItemId = (int)l.Item.Type, ItemWorldId = l.Item.World.Id }) .ToList <ILocationData>(), }; seedData.Worlds.Add(worldData); } return(seedData); }
public ISeedData GenerateSeed(IDictionary <string, string> options, string seed) { int randoSeed; if (string.IsNullOrEmpty(seed)) { randoSeed = System.Security.Cryptography.RandomNumberGenerator.GetInt32(0, int.MaxValue); seed = randoSeed.ToString(); } randoSeed = int.Parse(seed); var randoRnd = new Random(randoSeed); var config = new Config(options); var worlds = new List <World>(); /* FIXME: Just here to semi-obfuscate race seeds until a better solution is in place */ if (config.Race) { randoRnd = new Random(randoRnd.Next()); } if (config.GameMode == GameMode.Normal) { worlds.Add(new World(config, "Player", 0, new HexGuid())); } else { int players = options.ContainsKey("players") ? int.Parse(options["players"]) : 1; for (int p = 0; p < players; p++) { worlds.Add(new World(config, options[$"player-{p}"], p, new HexGuid())); } } var filler = new Filler(worlds, config, randoRnd); filler.Fill(); var playthrough = new Playthrough(worlds); var spheres = playthrough.Generate(); var seedData = new SeedData { Guid = new HexGuid(), Seed = seed, Game = Name, Mode = config.GameMode.ToLString(), Logic = $"{config.SMLogic.ToLString()}+{config.Z3Logic.ToLString()}", Playthrough = config.Race ? new List <Dictionary <string, string> >() : spheres, Worlds = new List <IWorldData>(), }; /* Make sure RNG is the same when applying patches to the ROM to have consistent RNG for seed identifer etc */ int patchSeed = randoRnd.Next(); foreach (var world in worlds) { var patchRnd = new Random(patchSeed); var patch = new Patch(world, worlds, seedData.Guid, randoSeed, patchRnd); var worldData = new WorldData { Id = world.Id, Guid = world.Guid, Player = world.Player, Patches = patch.Create(config) }; seedData.Worlds.Add(worldData); } return(seedData); }