예제 #1
0
        private void TestOnSampleMap(string moves, bool isSuccessful, int?timeUnits)
        {
            var solution = Emulator.MakeExtendedSolution(this.sampleMap, "test", CommandsSerializer.Parse(moves), string.Empty);

            Assert.Equal(isSuccessful, solution.IsSuccessful);
            Assert.Equal(timeUnits, solution.TimeUnits);
        }
예제 #2
0
        public void CloningSampleSolutionIsValid()
        {
            var map      = MapParser.Parse("(0,0),(10,0),(10,10),(0,10)#(0,0)#(4,2),(6,2),(6,7),(4,7);(5,8),(6,8),(6,9),(5,9)#B(0,1);F(0,2);L(0,3);R(0,4);C(0,5);C(0,6);C(0,7);X(0,9)", string.Empty);
            var commands = CommandsSerializer.Parse("WWWWWWWWWCDDDDDDESSSSSS#CDDDDDDDDESSSSSSSS#CSSDDDESSSSS#ESSSSSSSSSQDDDDD");
            var solution = Emulator.MakeExtendedSolution(map, "test", commands, string.Empty);

            Assert.True(solution.IsSuccessful);
            Assert.Equal(28, solution.TimeUnits);
        }
예제 #3
0
        private static void TestSerialization(
            string serializedMoves,
            params Command[]
            [] commands)
        {
            var parsedMoves         = CommandsSerializer.Parse(serializedMoves);
            var serializedBackMoves = CommandsSerializer.Serialize(commands);

            Assert.Equal(commands, parsedMoves);

            Assert.Equal(serializedMoves, serializedBackMoves);
        }
예제 #4
0
        public static void Main(string[] args)
        {
            const int Iterations = 1;

            for (var i = 0; i < Iterations; ++i)
            {
                var baseDir = args.Length > 0 ? args[0] : FindSolutionDir();
                Directory.SetCurrentDirectory(baseDir);

                var strategies = StrategyFactory.GenerateStrategies().ToArray();
                var packFile   = "Data/booster-pack.txt";
                var mapToPack  = File.ReadAllLines(packFile).Select(line => line.Split(' ')).ToDictionary(tokens => tokens[0], tokens => tokens[1]);

                var totalTimeUnits = 0;
                var haveFailures   = false;

                var outputLock = new object();

                Parallel.ForEach(
                    Directory.EnumerateFiles("Data/maps", "*.desc"),
                    new ParallelOptions {
                    MaxDegreeOfParallelism = 10
                },
                    mapFile =>
                {
                    var log     = new List <string>();
                    var mapName = Path.GetFileNameWithoutExtension(mapFile);

                    void Log(string msg)
                    {
                        if (LogImmediately)
                        {
                            Console.WriteLine($"{mapName}: {msg}");
                        }
                        else
                        {
                            log.Add(msg);
                        }
                    }

                    if (!mapToPack.ContainsKey(mapName))
                    {
                        return;
                    }

                    string packedBoosters = mapToPack.ContainsKey(mapName) ? mapToPack[mapName] : string.Empty;
                    Log($"Processing {mapName} with extra boosters: [{packedBoosters}]");
                    var map            = MapParser.Parse(File.ReadAllText(mapFile), packedBoosters);
                    var solutionSuffix = packedBoosters != string.Empty ? "-packed" : string.Empty;

                    var extSolutionPath = $"Data/extended-solutions{solutionSuffix}/{mapName}.ext-sol";

                    // Delete broken solutions
                    if (File.Exists(extSolutionPath))
                    {
                        var oldSolution = ExtendedSolution.Load(extSolutionPath);
                        var oldCommands = CommandsSerializer.Parse(oldSolution.Commands);
                        if (!Emulator.MakeExtendedSolution(map, string.Empty, oldCommands, packedBoosters).IsSuccessful)
                        {
                            File.Delete(extSolutionPath);
                        }
                    }

                    var rng = new Random();
                    var currentStrategies = StrategiesLimit != null
                            ? strategies.OrderBy(s => rng.Next()).Take(StrategiesLimit.Value).ToArray()
                            : strategies;

                    var solutions = currentStrategies.AsParallel()
                                    .Where(strategy => !(mapName.Contains("294") && strategy.Name.Contains("DumbBfs")))
                                    .Select(strategy => (strategy, Emulator.MakeExtendedSolution(map, strategy, packedBoosters)));

                    var numSuccessful = 0;
                    foreach (var pair in solutions)
                    {
                        var(strategy, solution) = pair;
                        solution.SaveIfBetter(extSolutionPath);
                        if (solution.IsSuccessful)
                        {
                            Log($"  {strategy.Name}: {solution.TimeUnits}");
                            if (StrategiesLimit != null && ++numSuccessful >= StrategiesLimit)
                            {
                                break;
                            }
                        }
                    }

                    var best = ExtendedSolution.Load(extSolutionPath);
                    File.WriteAllText($"Data/solutions{solutionSuffix}/{mapName}.sol", best.Commands);
                    if (solutionSuffix != string.Empty)
                    {
                        File.WriteAllText($"Data/solutions{solutionSuffix}/{mapName}.buy", packedBoosters);
                    }

                    Log($"  BEST ({best.StrategyName}): {best.IsSuccessful}/{best.TimeUnits}");

                    lock (outputLock)
                    {
                        if (best.TimeUnits.HasValue)
                        {
                            totalTimeUnits += best.TimeUnits.Value;
                        }
                        else
                        {
                            haveFailures = true;
                        }

                        foreach (var line in log)
                        {
                            Console.WriteLine(line);
                        }
                    }
                });
예제 #5
0
        public IEnumerable <Command[]> SolveWithClones(State state)
        {
            var addedBots = new List <(int time, State.Bot bot)>();
            var time      = 0;

            var cloningCommands = MakeClones().ToList();
            var cloningTime     = cloningCommands.Count;

            var stateAfterCloning = state;

            var firstBotSolutionSize = this.baseStrategy
                                       .Solve(stateAfterCloning.ReplaceBots(resetBoosters: false, stateAfterCloning.GetBot(0)))
                                       .Count();

            var totalBonusTime = addedBots.Sum(tup => cloningTime - tup.time);
            var stepsPerBot    = Math.Min(
                firstBotSolutionSize / (1 + addedBots.Count),
                Math.Max(0, firstBotSolutionSize - totalBonusTime) / (1 + addedBots.Count));

            while (true)
            {
                var commandsPerBot = new Command[addedBots.Count + 1][];

                var botState = stateAfterCloning.ReplaceBots(resetBoosters: false, state.GetBot(0));
                var bot      = botState.GetBot(0);
                var botIdx   = 0;

                while (true)
                {
                    var bonusTime = botIdx == 0
                        ? 0
                        : cloningTime - addedBots[botIdx - 1].time;
                    var left        = stepsPerBot + bonusTime;
                    var commandsBuf = new List <Command>();
                    foreach (var cmd in this.baseStrategy.Solve(botState))
                    {
                        if (left-- <= 0)
                        {
                            break;
                        }

                        commandsBuf.Add(cmd.Single());

                        var nextState = botState.Next(cmd);
                        if (nextState == null)
                        {
                            throw new Exception("shouldn't happen");
                        }

                        botState = nextState;
                    }

                    commandsPerBot[botIdx] = commandsBuf.ToArray();

                    if (++botIdx >= stateAfterCloning.BotsCount)
                    {
                        break;
                    }

                    botState = botState.ReplaceBots(resetBoosters: true, addedBots[botIdx - 1].bot);
                }

                if (botState.Map.CellsToVisit.Count == botState.WrappedCellsCount)
                {
                    commandsPerBot[0] = cloningCommands.Concat(commandsPerBot[0]).ToArray();
                    foreach (var cmds in CommandsSerializer.Transponse(commandsPerBot))
                    {
                        yield return(cmds);
                    }

                    break;
                }

                stepsPerBot = (int)(1 + (stepsPerBot * 1.1));
            }

            IEnumerable <Command> MakeClones()
            {
                var map = state.Map;
                var bfs = new BfsState(map);

                while (addedBots.Count < map.NumCloneBoosts)
                {
                    var bot = state.GetBot(0);

                    foreach (var cmd in FindBooster())
                    {
                        ++time;
                        state = state.Next(cmd) ?? throw new Exception("Impossible");
                        yield return(cmd);
                    }

                    while (map[bot.X, bot.Y] == Map.Cell.SpawnPoint && state.CloneBoosterCount > 0)
                    {
                        ++time;
                        addedBots.Add((time, bot));
                        state = state.Next(Clone.Instance) ?? throw new Exception("Impossible");
                        yield return(Clone.Instance);
                    }
                }

                IEnumerable <Command> FindBooster()
                {
                    var bot = state.GetBot(0);

                    ++bfs.Generation;
                    bfs.Queue.Clear();
                    bfs.Queue.Enqueue((bot.X, bot.Y, bot.Dir));
                    bfs.Nodes[bot.X, bot.Y, 0] = new BfsState.Node(bfs.Generation, -1, 0);
                    while (bfs.Queue.Count > 0)
                    {
                        var(x, y, dir) = bfs.Queue.Dequeue();

                        if ((map[x, y] == Map.Cell.Clone && !state.IsPickedUp(x, y) && (x, y) != (bot.X, bot.Y)) ||
                            (map[x, y] == Map.Cell.SpawnPoint &&
                             (state.CloneBoosterCount > 0 || (map[bot.X, bot.Y] == Map.Cell.Clone && !state.IsPickedUp(bot.X, bot.Y)))))
                        {
                            bfs.FindBackwardPath(x, y, 0, bot);
                            return(bfs.Path);
                        }

                        for (var i = 0; i < Move.All.Length; ++i)
                        {
                            var move = Move.All[i];
                            var nx   = x + move.Dx;
                            var ny   = y + move.Dy;
                            if (map.IsFree(nx, ny) && bfs.Nodes[nx, ny, dir].Generation != bfs.Generation)
                            {
                                bfs.Nodes[nx, ny, dir] = new BfsState.Node(bfs.Generation, i, 0);
                                bfs.Queue.Enqueue((nx, ny, dir));
                            }
                        }
                    }

                    throw new Exception("oops");
                }
            }
        }