Ejemplo n.º 1
0
            public IEnumerable <ICommand> MakeTrace(bool noHalt = false)
            {
                var idleSteps = 0;

                while (true)
                {
                    var idle = true;
                    botPositions.Clear();
                    interferedCells.Clear();

                    foreach (var bot in bots)
                    {
                        botPositions.Add(bot.Coord, bot);
                        interferedCells.Add(bot.Coord);
                    }

                    var newBots           = new List <Bot>();
                    int numDeadBots       = 0;
                    var changedCoords     = new List <TCoord>();
                    int numPlannedFusions = bots.Count(b => b.FusionSTarget != null);
                    idleBots = 0;

                    foreach (var b in bots)
                    {
                        b.Acted              = false;
                        b.MustDie            = false;
                        b.ActedFusionPTarget = null;
                        b.ActedFusionSTarget = null;
                        --b.FissionTimeout;
                        if (b.IdleTooLong)
                        {
                            ++idleBots;
                        }
                    }

                    if (Trace)
                    {
                        Console.WriteLine($"-----");
                    }

                    if ((availablePositions.Count == 0) && (bots.Count == 1) && bots[0].Coord.IsAtStart())
                    {
                        if (!noHalt)
                        {
                            yield return(new Halt());
                        }

                        yield break;
                    }

                    if (availablePositions.Count != 0)
                    {
                        currentDepth = availablePositions.Select(Depth).Max();
                    }

                    availableAtThisLevel = availablePositions.Count(p => Depth(p) == currentDepth);

                    foreach (var bot in bots)
                    {
                        if ((bot.Target == null) || !CanMove(bot) || (bot.FillTarget != null && Depth(bot.FillTarget.Value) != currentDepth))
                        {
                            if (Trace)
                            {
                                //Console.WriteLine($"!{bot.IdleTime}");
                            }

                            ChooseNewTarget(bot, newBots, ref numPlannedFusions);
                            if (bot.Target != null && !CanMove(bot))
                            {
                                throw new Exception("Something bad happened");
                            }
                        }

                        if ((bot.Target != null) && CanMove(bot))
                        {
                            var pc  = bot.Coord;
                            var cmd = MoveBot(bot, newBots, ref numDeadBots, changedCoords);
                            if (cmd is Wait)
                            {
                                ++bot.IdleTime;
                            }
                            else
                            {
                                idle         = false;
                                bot.IdleTime = 0;
                            }

                            yield return(cmd);

                            if (Trace)
                            {
                                Console.WriteLine($"{bot.Id} move {pc} -> {bot.Coord} ({!bot.MustDie}, {numDeadBots})");
                            }
                        }
                        else
                        {
                            if (Trace)
                            {
                                Console.WriteLine($"{bot.Id} waits at {bot.Coord}  ({model[bot.Coord]}/{state.M(bot.Coord)}/{Depth(bot.Coord)}");
                            }

                            ++bot.IdleTime;

                            yield return(new Wait());
                        }

                        bot.Acted = true;
                    }

                    if (idle)
                    {
                        // we are stuck. Just produce some garbage trace
                        if (++idleSteps >= 3)
                        {
                            Console.WriteLine($"STUCK  {numFilled}/{model.NumFilled}");
                            if (Trace)
                            {
                                foreach (var b in bots)
                                {
                                    ChooseNewTarget(b, newBots, ref numPlannedFusions);
                                    Console.WriteLine($"{b.Id}: {b.Coord}, T: {b.Target}");
                                }

                                Console.WriteLine($"Cur depth: {currentDepth}");
                                foreach (var c in availablePositions.Where(c => Depth(c) == currentDepth))
                                {
                                    Console.WriteLine($"  A: {c}");
                                }
                            }

                            yield break;
                            throw new Exception("STUCK");
                        }
                    }
                    else
                    {
                        idleSteps = 0;
                    }

                    if (newBots.Count > 0)
                    {
                        // Console.WriteLine("HEY");
                        bots.AddRange(newBots);
                        bots = bots.OrderBy(bot => bot.Id).ToList();
                    }

                    if (numDeadBots != 0)
                    {
                        bots = bots.Where(bot => !bot.MustDie).ToList();

                        foreach (var b in bots)
                        {
                            var seeds = string.Join(",", b.Seeds);
                            if (Trace)
                            {
                                Console.WriteLine($"{b.Id}: {b.Coord}, S: {seeds}");
                            }
                        }
                    }

                    foreach (var c in changedCoords)
                    {
                        if (mode == Mode.Assembly)
                        {
                            state.Matrix[c.X, c.Y, c.Z] = 1;
                            foreach (var n in c.ManhattenNeighbours())
                            {
                                if (n.IsValid(model.R) && model[n] != 0 && !addedPositions.Contains(n))
                                {
                                    addedPositions.Add(n);
                                    availablePositions.Add(n);
                                }
                            }
                        }
                        else
                        {
                            if (Trace)
                            {
                                foreach (var cc in availablePositions)
                                {
                                    if (state.M(cc) == 0)
                                    {
                                        throw new Exception("WTF");
                                    }
                                }
                            }

                            state.Matrix[c.X, c.Y, c.Z] = 0;
                            foreach (var n in c.ManhattenNeighbours())
                            {
                                if (n.IsValid(model.R) && state.M(n) != 0 && !addedPositions.Contains(n))
                                {
                                    addedPositions.Add(n);
                                    availablePositions.Add(n);
                                }
                            }

                            if (Trace)
                            {
                                foreach (var cc in availablePositions)
                                {
                                    if (state.M(cc) == 0)
                                    {
                                        throw new Exception("WTF");
                                    }
                                }
                            }
                        }
                    }

                    if (Trace)
                    {
                        if (availablePositions.Count != 0)
                        {
                            currentDepth = availablePositions.Select(Depth).Max();
                        }

                        Console.WriteLine(
                            $"  {numFilled} / {model.NumFilled}. {availablePositions.Count(p => Depth(p) == currentDepth)} for {bots.Count} bots");
                    }

                    if (changedCoords.Count != 0)
                    {
                        numFilled += changedCoords.Count;

                        /*
                         *                      foreach (var c in availablePositions.Where(c => Depth(c) == currentDepth))
                         *                      {
                         *                          Console.WriteLine($"  A: {c}");
                         *                      }
                         */
                    }
                }
            }
Ejemplo n.º 2
0
 private bool IsFree(TCoord coord, int maxDepth) =>
 (state.M(coord) == 0) &&
 // depth[coord.X, coord.Y, coord.Z] < maxDepth &&
 !interferedCells.Contains(coord);