public static N8Level GetRandomForest()
        {
            N8Level forest = Utilities.GetDefault();

            Random rand = new Random();

            for (int i = 0; i < 300; i++)
            {
                N8Block b = forest.blocks.GenerateBlock(TreeTypes[i % TreeTypes.Length], TreeNames[i % TreeNames.Length]);
                b.position = rand.NextVector(new Vector3D(-2000, -2000, 75), new Vector3D(2000, 2000, 65));
                b.rotation = new Quaternion(new Vector3D(0, 0, 1), rand.Next(360));
            }

            MinorModifiers.OrderLoading(forest, new Vector3D(1, 0, 0));

            return forest;
        }
        private static void FleeTronics(N8BlockFactory LevelBlocks, List<FlowTronic> alerts, bool rotate = true, bool AttachLevelBlocks = false, string password = null)
        {
            Quaternion UpsideDown = new Quaternion(new Vector3D(1, 0, 0), 180);

            FlowTronic InitTronic;
            if (password == null)
            {
                InitTronic = LevelBlocks.Keyboard("Set Cell Password");
                InitTronic.position = new Vector3D(30, -30, 5);
            }
            else
            {
                InitTronic = LevelBlocks.Button(1, "Setup Reciever");
            }

            TronicSequence Reciever = new TronicSequence(InitTronic);

            DataBlock Channel = Reciever.NewDataBlock("Channel", "1025");
            DataBlock UsernameRec = Reciever.NewDataBlock("Recieved Username");
            DataBlock MessageRec = Reciever.NewDataBlock("Recieved Message");

            DataBlock UsernameStore = Reciever.NewDataBlock("Stored Username", "Tacroy");
            //Not used atm
            //DataBlock AlternateUsernameStore = Reciever.NewDataBlock("Alternate Username", "nobody");
            DataBlock Password = Reciever.NewDataBlock("Password", password ?? "");
            if (password == null)
            {
                InitTronic.DataOutA(Password.Out);
            }

            Reciever.RadioReciever(Channel.In, UsernameRec.Out, MessageRec.Out);

            TronicSequence PasswordTest = new TronicSequence();

            PasswordTest.IfEqual(Password.In, MessageRec.In, "PasswordCheck");

            TronicSequence NameTest = new TronicSequence();

            NameTest.IfEqual(UsernameRec.In, UsernameStore.In, "NameCheck");

            TronicSequence FlipFlop = TronicsTesting.Ringbuffer(new List<string>(new string[] { "0", "1" }));
            DataBlock ControlBit = FlipFlop.data[FlipFlop.data.Count - 1];
            DataBlock ReturnPos = Reciever.NewDataBlock("Return Position", "v0,0,0");

            Reciever.Append(NameTest)
                    .Append(PasswordTest)
                    .Append(FlipFlop)
                    .Mover(ReturnPos.In, ReturnPos.Out, "Return Mover")
                    .RadioTransmit(Channel.In, ControlBit.In, "Yeller");

            TronicSequence RandomBottomVector = TronicsTesting.RandomXYVectorGenerator(-1000, 1000, -1000);
            TronicSequence RandomTopVector = TronicsTesting.RandomXYVectorGenerator(-2000, 2000, 2000);
            DataBlock RandVectTop = RandomTopVector.data[RandomTopVector.data.Count - 1];
            DataBlock RandVectBottom = RandomBottomVector.data[RandomBottomVector.data.Count - 1];

            Random rand = new Random();

            Vector3D AttachOffset = rand.NextVector(new Vector3D(60,60,0), new Vector3D(-60,-60,0));

            foreach (FlowTronic alert in alerts)
            {
                alert.position += AttachOffset;
                RandomTopVector.GetFirst().FlowInFrom(alert);
            }

            N8Block TronicAttach = LevelBlocks.GenerateBlock("letter.period", "Attach Point");
            TronicAttach.position = -AttachOffset;
            TronicAttach.position.Z = 500;

            TronicSequence MovementLogic = new TronicSequence();
            MovementLogic.Append(RandomTopVector);

            MovementLogic.IfGreater(ControlBit.In, null, "Control");

            if (rotate)
            {
                TronicSequence ProxyRotor = new TronicSequence();
                DataBlock Quantity = ProxyRotor.NewDataBlock("Amount", "q0,0,1,0");
                DataBlock Current = ProxyRotor.NewDataBlock("Current", "q1,0,0,0");

                ProxyRotor.Multiply(Quantity.In, Current.In, Current.Out, "Unit step")
                          .Rotor(Current.In, null, "Rotate1");
                MovementLogic.Append(ProxyRotor);
            }
            //Mega and vacubombs take 15 seconds to explode, regular 10. Add 2 seconds up in the sky for a buffer.
            //Also keep in mind that because we fly up then delay, once we're up there we're a random sky mover so that should be safe enough.
            DataBlock DelayTime = MovementLogic.NewDataBlock("Delay", "17");
            MovementLogic.Mover(RandVectTop.In, null, "Flee Mover 1")
                         .Delay(DelayTime.In)
                         .Append(RandomBottomVector)
                         .Mover(RandVectBottom.In, null, "Flee Mover 2");

            MovementLogic.GetCurrent().Item1.FlowOutTo((FlowTronic)Reciever.tronics.Tronics.Last());

            MovementLogic.LayoutDense(AttachOffset);
            Reciever.LayoutDense(AttachOffset);

            //Attach everything
            Reciever.AttachAllNonPositional(TronicAttach, false);
            MovementLogic.AttachAllNonPositional(TronicAttach, false);

            foreach (N8Tronic t in alerts)
            {
                TronicAttach.AttachToMe(t);
            }

            LevelBlocks.CopyFromDestructive(MovementLogic.tronics);
            LevelBlocks.CopyFromDestructive(Reciever.tronics);

            if (AttachLevelBlocks)
            {
                foreach (N8Block b in from N8Block t in LevelBlocks.Blocks where t.name != "Attach Point" select t)
                {
                    b.position += AttachOffset;
                    TronicAttach.AttachToMe(b);
                }
            }

            N8Tronic RetMover = (from N8Tronic t in LevelBlocks.Tronics where t.name == "Return Mover" select t).First();
            N8Tronic FleeMover1 = (from N8Tronic t in LevelBlocks.Tronics where t.name == "Flee Mover 1" select t).First();
            N8Tronic FleeMover2 = (from N8Tronic t in LevelBlocks.Tronics where t.name == "Flee Mover 2" select t).First();

            RetMover.position.Z = -1000;
            FleeMover1.position.Z = 0;
            FleeMover1.position.X = -30;
            FleeMover2.position.Z = 0;
            FleeMover2.position.X = 30;
            RetMover.Detach();
            FleeMover1.Detach();
            FleeMover2.Detach();

            if (rotate)
            {
                N8Tronic Rotor = (from N8Tronic t in LevelBlocks.Tronics where t.name == "Rotate1" select t).First();
                TronicAttach.AttachToMe(Rotor);
            }

            Console.WriteLine("Total block count: " + (LevelBlocks.Blocks.Count + LevelBlocks.Tronics.Count));
        }
        public static N8Level GetCrossroads()
        {
            N8Level Level = new N8Level(); //MaxProtectTest.GetProxyBubble();
            MinorModifiers.AddCrossroads(Level);
            Random rand = new Random();

            int NumBlocks = 349 - (Level.blocks.Tronics.Count + Level.blocks.Blocks.Count);
            Console.WriteLine(NumBlocks);
            Console.ReadLine();
            for (int i = 0; i < NumBlocks; i++)
            {
                string color = colors[i % colors.Length];
                //string color = "black";
                N8Block CurrentBlock = Level.blocks.GenerateBlock("simple." + color + ".block", names[rand.Next(names.Length)]);
                //Keep it out of the crossroads
                CurrentBlock.position = rand.NextVector(new Vector3D(2000, 2000, -1000), new Vector3D(300, 300, 2000));

                //And flop it around the quadrants randomly
                if (rand.Next(0, 2) == 0)
                {
                    CurrentBlock.position.X *= -1;
                }
                if (rand.Next(0, 2) == 0)
                {
                    CurrentBlock.position.Y *= -1;
                }

                CurrentBlock.rotation = rand.NextQuaternion();
            }
            MinorModifiers.OrderLoadingCylindrical(Level);
            return Level;
        }
        public static N8Level GetBlockRoad(bool diagonal = false)
        {
            N8Level Level = new N8Level();
            Random rand = new Random();
            int NumBlocks = 349;
            if (diagonal)
            {
                Vector3D diag1 = new Vector3D(1, 1, 0);
                diag1.Normalize();
                Vector3D diag2 = new Vector3D(1, -1, 0);
                diag2.Normalize();
                //Max distance for a diagonal is Sqrt(4000^2 + 4000^2) ~= 5656, and add an extra two just to make sure it reaches the edges
                int Min = -5658 / 2;
                int Max = 5658 / 2;
                for (int i = 0; i < NumBlocks; i++)
                {
                    int mag = rand.Next(Min, Max);
                    string color = colors[i % colors.Length];
                    N8Block CurrentBlock = Level.blocks.GenerateBlock("simple." + color + ".block", names[rand.Next(names.Length)]);

                    if (rand.Next(0, 2) == 0)
                    {
                        CurrentBlock.position = diag1 * mag;
                    }
                    else
                    {
                        CurrentBlock.position = diag2 * mag;
                    }

                    CurrentBlock.rotation = rand.NextQuaternion();
                }
            }
            else
            {
                for (int i = 0; i < NumBlocks; i++)
                {
                    string color = colors[i % colors.Length];
                    N8Block CurrentBlock = Level.blocks.GenerateBlock("simple." + color + ".block", names[rand.Next(names.Length)]);
                    //Either put them in the x-coord area or the y-coord area (yes this means the center will be better covered)
                    if (rand.Next(0, 2) == 0)
                    {
                        CurrentBlock.position = rand.NextVector(new Vector3D(-100, 2000, 0), new Vector3D(100, -2000, 0));
                    }
                    else
                    {
                        CurrentBlock.position = rand.NextVector(new Vector3D(2000, -100, 0), new Vector3D(-2000, 100, 0));
                    }
                    CurrentBlock.rotation = rand.NextQuaternion();
                }
            }

            MinorModifiers.OrderLoading(Level, new Vector3D(1, 1, 0));

            return Level;
        }