示例#1
0
        public virtual void Bind(Module module, Dictionary <string, BoardFluid> FluidVariableLocations)
        {
            BoundModule = module;
            //module.BindingOperation = this;

            //The fluid types of the module layout, is changedto fit with the operation.
            //Thus for example, when the module is removed when the operations have finished,
            //the remaining droplets will have the correct type, and can be used by operations requiring the output of that module.

            int currentDroplet = 0;

            foreach (var fluid in InputFluids)
            {
                BoardFluid fluidType = new BoardFluid(fluid.OriginalFluidName);
                for (int i = 0; i < fluid.GetAmountInDroplets(FluidVariableLocations); i++)
                {
                    module.GetInputLayout().Droplets[currentDroplet].SetFluidType(fluidType);
                    currentDroplet++;
                }
            }
            BoardFluid outputFluidType = new BoardFluid(OutputVariable);

            foreach (var droplet in module.GetOutputLayout().Droplets)
            {
                droplet.SetFluidType(outputFluidType);
            }
        }
示例#2
0
        private static void DiscardDroplets(BoardFluid oldFluidType)
        {
            //This is done by changing their internal names,
            //so they can never be used in any operation later on.
            BoardFluid            overwrittingFluidType = new BoardFluid(WASTE_FLUIDNAME_STRING);
            List <IDropletSource> dropletSources        = new List <IDropletSource>(oldFluidType.dropletSources);

            foreach (var dropletSource in dropletSources)
            {
                dropletSource.SetFluidType(overwrittingFluidType);
            }
        }
示例#3
0
        private (BoardFluid, int) RecordNewFluidType(string fluidName, int currentTime, FluidBlock operation)
        {
            //If there already are droplets associated with the fluid name
            //they must be overwritten or moved to a waste module
            currentTime = RemoveFluidVariable(fluidName, currentTime, operation);

            BoardFluid fluidType = new BoardFluid(fluidName);

            if (!FluidVariableLocations.ContainsKey(fluidName))
            {
                NewVariablesCreatedInThisScope.Add(fluidName);
            }
            FluidVariableLocations[fluidName] = fluidType;
            return(fluidType, currentTime);
        }
示例#4
0
        private BoardFluid RecordCompletlyNewFluidType(String fluidName)
        {
            if (FluidVariableLocations.ContainsKey(fluidName))
            {
                throw new InternalRuntimeException("Logic error: RecordCompletlyNewFluidType is only for fluid names that have never been used before.");
            }
            BoardFluid fluidType = new BoardFluid(fluidName);

            if (!FluidVariableLocations.ContainsKey(fluidName))
            {
                NewVariablesCreatedInThisScope.Add(fluidName);
            }
            FluidVariableLocations[fluidName] = fluidType;
            return(fluidType);
        }
示例#5
0
 public void PlaceStaticModules(List <StaticDeclarationBlock> staticDeclarations)
 {
     foreach (var staticDeclaration in staticDeclarations)
     {
         if (staticDeclaration is DropletDeclaration dropletDeclaration)
         {
             throw new NotImplementedException();
             BoardFluid fluidType     = RecordCompletlyNewFluidType(dropletDeclaration);
             Droplet    droplet       = (Droplet)dropletDeclaration.getAssociatedModule();
             bool       couldBePlaced = board.FastTemplatePlace(droplet);
             if (!couldBePlaced)
             {
                 throw new RuntimeException("The input module couldn't be placed. The module is: " + droplet.ToString());
             }
             //It is not really static, and thus must does not need to be registered as such.
         }
         else if (staticDeclaration is InputDeclaration input)
         {
             BoardFluid  fluidType     = RecordCompletlyNewFluidType(input);
             InputModule inputModule   = new InputModule(fluidType, (int)input.Amount);
             bool        couldBePlaced = board.FastTemplatePlace(inputModule);
             if (!couldBePlaced)
             {
                 throw new RuntimeException("The input module couldn't be placed. The module is: " + inputModule.ToString());
             }
             input.BoundModule = inputModule;
             inputModule.RepositionLayout();
             StaticModules.Add(staticDeclaration.ModuleName, inputModule);
             NameOfInputFluids.Add(fluidType.FluidName);
         }
         else
         {
             Module staticModule = getAndPlaceFirstPlaceableModule(staticDeclaration, board);
             StaticModules.Add(staticDeclaration.ModuleName, staticModule);
         }
     }
     if (SHOULD_DO_GARBAGE_COLLECTION)
     {
         WasteModule waste         = new WasteModule();
         bool        couldBePlaced = board.FastTemplatePlace(waste);
         if (!couldBePlaced)
         {
             throw new RuntimeException("The waste module couldn't be placed. The module is: " + waste.ToString());
         }
         waste.GetInputLayout().Reposition(waste.Shape.x, waste.Shape.y);
         StaticModules.Add(WASTE_MODULE_NAME, waste);
     }
 }
示例#6
0
文件: Router.cs 项目: TheAIBot/Bioly
        public static Route RouteSingleDropletToModule(FluidBlock operation, Board board, int currentTime, Droplet dropletInput)
        {
            BoardFluid InputFluidType = dropletInput.GetFluidType();
            Route      route          = RouteSingleDropletToModule(operation.BoundModule, board, currentTime, dropletInput);

            //The route is added to the module's routes:
            List <Route> inputRoutes;

            operation.InputRoutes.TryGetValue(InputFluidType.FluidName, out inputRoutes);
            if (inputRoutes == null)
            {
                inputRoutes = new List <Route>();
                operation.InputRoutes.Add(InputFluidType.FluidName, inputRoutes);
            }
            inputRoutes.Add(route);
            return(route);
        }
示例#7
0
文件: Router.cs 项目: TheAIBot/Bioly
        public static Route RouteSingleDropletToModule(Module module, Board board, int currentTime, Droplet dropletInput)
        {
            BoardFluid InputFluidType = dropletInput.GetFluidType();

            if (InputFluidType.GetNumberOfDropletsAvailable() < 1)
            {
                throw new RuntimeException("There isn't enough droplets of type " + InputFluidType.FluidName +
                                           " avaiable, to satisfy the requirement of the module: " + module.ToString());
            }
            //Routes a droplet of type InputFluid to the module.
            Route route = DetermineRouteToModule(haveReachedDropletOfTargetType(dropletInput), module, dropletInput, board, currentTime); //Will be included as part of a later step.

            if (route == null)
            {
                throw new InternalRuntimeException("No route found. This should not be possible.");
            }

            //The droplet has been "used up"/it is now inside a module,
            //so it needs to be removed from its original position:
            RemoveRoutedDropletFromBoard(board, route);
            return(route);
        }
示例#8
0
        private int DoGarbageCollection(int currentTime, FluidBlock operation, BoardFluid oldFluidType)
        {
            int         numberOfDropletsToRoute = oldFluidType.GetNumberOfDropletsAvailable();
            WasteModule waste = (WasteModule)StaticModules[WASTE_MODULE_NAME];

            waste.GetInputLayout().Droplets[0].FakeSetFluidType(oldFluidType);
            Droplet dropletInput = waste.GetInputLayout().Droplets[0];

            List <Route> wasteRoutes = new List <Route>();

            for (int i = 0; i < numberOfDropletsToRoute; i++)
            {
                Route route = Router.RouteSingleDropletToModule(waste, board, currentTime, dropletInput);
                wasteRoutes.Add(route);
                //The route is scheduled sequentially, so the end time of the current route (+1) should be the start of the next.
                //This will give an overhead of +1 for the operation starting time, for each droplet routed:
                currentTime = route.getEndTime() + 1;
            }
            if (wasteRoutes.Count > 0)
            {
                operation.WasteRoutes.Add(oldFluidType.FluidName, wasteRoutes);
            }
            return(currentTime);
        }
示例#9
0
        private int ExtractAndReassignDroplets(int currentTime, FluidBlock nextOperation, int requiredDroplets, BoardFluid targetFluidType, BoardFluid inputFluid)
        {
            //First it is checked if there is there even any fluid that needs to be transfered:
            if (requiredDroplets == 0)
            {
                return(currentTime);
            }
            int originalStartTime = currentTime;


            //Fluid needs to be allocated to a variable.
            //If the origin of the fluid is an input, a given amount of droplets needs to moved unto the board,
            //but if origin is simply droplets placed on the board, a simple renaiming can be done instead.
            //It will prioritize taking droplets already on the board, instead of taking droplets out of the inputs.

            //Trying to take as many droplets as possible from those already placed on the board,
            //to minimize the number of droplets that must be taken from the input modules:
            List <Droplet> availableDroplets = inputFluid.dropletSources.Where(dropletSource => dropletSource is Droplet)
                                               .Select(dropletSource => dropletSource as Droplet)
                                               .ToList();
            int numberOfDropletsToTransfer = Math.Min(availableDroplets.Count, requiredDroplets);

            for (int i = 0; i < numberOfDropletsToTransfer; i++)
            {
                availableDroplets[i].SetFluidType(targetFluidType);
            }
            int numberOfDropletsTransfered = numberOfDropletsToTransfer;

            if (numberOfDropletsTransfered != requiredDroplets)
            {
                //As there aren't enough droplets placed on the board, to satisfy the requirement,
                //some must be taken from the input modules.
                List <InputModule> inputModules = inputFluid.dropletSources.Where(dropletSource => dropletSource is InputModule)
                                                  .Select(dropletSource => dropletSource as InputModule)
                                                  .ToList();
                List <Route> dropletRoutes = new List <Route>();
                nextOperation.InputRoutes.Add(inputFluid.FluidName, dropletRoutes);
                foreach (var inputModule in inputModules)
                {
                    while (inputModule.DropletCount > 0 && numberOfDropletsTransfered < requiredDroplets)
                    {
                        numberOfDropletsTransfered++;
                        inputModule.DecrementDropletCount();
                        Droplet droplet = new Droplet(targetFluidType, NameOfInputFluids);
                        droplet.SetFluidConcentrations(inputModule);
                        bool couldPlace = board.FastTemplatePlace(droplet);
                        if (!couldPlace)
                        {
                            throw new RuntimeException("Not enough space for the fluid transfer.");
                        }
                        Route route = Router.RouteDropletToNewPosition(inputModule, droplet, board, currentTime);
                        currentTime = route.getEndTime() + 1;
                        dropletRoutes.Add(route);
                    }
                    if (numberOfDropletsTransfered == requiredDroplets)
                    {
                        break;
                    }
                }
                if (numberOfDropletsTransfered != requiredDroplets)
                {
                    throw new RuntimeException("Not enough droplets available. Fluid name: " + inputFluid.FluidName);
                }
            }
            else
            {
                currentTime += 1; //Necessary for the recording of the board below.
            }

            rectanglesAtDifferentTimes.Add(currentTime, board.CopyAllRectangles());
            currentTime += 2;
            return(currentTime);
        }
示例#10
0
        public static (Board board, List <(Rectangle, int)> rectangles, List <(Module, int)> modules) ArrayToRectangles(int[] array, int arrayWidth, string fluidName = "random")
        {
            Assert.AreEqual(0, array.Length % arrayWidth);

            Board board = new Board(arrayWidth, array.Length / arrayWidth);

            board.EmptyRectangles.Clear();

            Dictionary <int, List <(int x, int y)> > rectangleData = new Dictionary <int, List <(int x, int y)> >();

            array.Distinct().Where(x => x != 0).ForEach(x => rectangleData.Add(x, new List <(int, int)>()));

            for (int y = 0; y < array.Length / arrayWidth; y++)
            {
                for (int x = 0; x < arrayWidth; x++)
                {
                    int value = array[y * arrayWidth + x];
                    if (value != 0)
                    {
                        rectangleData[value].Add((x, y));
                    }
                }
            }
            BoardFluid fluid = new BoardFluid(fluidName);
            List <(Rectangle rect, int id)> rectangles = new List <(Rectangle, int)>(rectangleData.Count);
            List <(Module rect, int id)>    modules    = new List <(Module, int)>(rectangleData.Count);

            foreach (var data in rectangleData.OrderBy(x => x.Key).Select(x => x))
            {
                int minX = data.Value.Min(d => d.x);
                int minY = data.Value.Min(d => d.y);
                int maxX = data.Value.Max(d => d.x);
                int maxY = data.Value.Max(d => d.y);

                int x      = minX;
                int y      = minY;
                int width  = maxX - minX + 1;
                int height = maxY - minY + 1;

                Rectangle newRectangle = new Rectangle(width, height, x, y);
                rectangles.Add((newRectangle, data.Key));

                if (data.Key < 0)
                {
                    Droplet module = new Droplet(fluid);
                    module.Shape         = newRectangle;
                    newRectangle.isEmpty = false;
                    board.PlacedModules.Add(module, module);
                    modules.Add((module, data.Key));
                    board.UpdateGridAtGivenLocation(module, newRectangle);
                }
                else
                {
                    board.EmptyRectangles.Add(newRectangle, newRectangle);
                }
            }

            //Make adjacencies between all the rectangles
            List <Rectangle> onlyRectangles = rectangles.Select(x => x.rect).ToList();

            rectangles.ForEach(x => x.rect.Connect(onlyRectangles));

            return(board, rectangles, modules);
        }