Esempio n. 1
0
        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();
            }
            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 = 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++)
                {
                    var found = options.TryGetValue($"player-{p}", out var player);
                    if (!found || !alphaNumeric.IsMatch(player))
                    {
                        throw new ArgumentException($"Name for player {p + 1} not provided, or contains no alphanumeric characters");
                    }
                    worlds.Add(new World(config, player, p, new HexGuid()));
                }
            }

            var filler = new Filler(worlds, config, randoRnd);

            filler.Fill();

            var playthrough = new Playthrough(worlds, config);
            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, 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);
        }
Esempio n. 2
0
        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);
        }