Exemplo n.º 1
0
        public static SolutionParameters FromFactory(int width, int height, RecipeGraph factory)
        {
            if (factory == null)
            {
                throw new ArgumentNullException("factory");
            }

            var result = new SolutionParameters(width, height);

            result.SinkPositions = factory.OutputNodes.Concat(factory.WasteNodes).Select((s) => new KeyValuePair <SinkStep, Vector2>(s, Vector2.Zero)).ToImmutableDictionary();

            result.SourcePositions = factory.InputNodes.Select((s) => new KeyValuePair <SourceStep, Vector2>(s, Vector2.Zero)).ToImmutableDictionary();

            var buildings = factory.Transformations.Cast <ProductionStep>().ToImmutableList();

            result.BuildingPositions = buildings.Select((b) => new KeyValuePair <ProductionStep, Tuple <Vector2, BuildingRotation> >(b, new Tuple <Vector2, BuildingRotation>(Vector2.Zero, BuildingRotation.North))).ToImmutableDictionary();

            var buildingInputs  = buildings.SelectMany((b) => b.Recipe.Ingredients.Select((i) => new Tuple <IStep, Item, bool>(b, i.Item, true)));
            var buildingOutputs = buildings.SelectMany((b) => b.Recipe.Results.Select((i) => new Tuple <IStep, Item, bool>(b, i.Item, false)));
            var sinkInputs      = result.SinkPositions.Keys.Select((s) => new Tuple <IStep, Item, bool>(s, s.Item.Item, true));
            var sourceOutputs   = result.SourcePositions.Keys.Select((s) => new Tuple <IStep, Item, bool>(s, s.Item.Item, false));

            result.Connections = buildingInputs.Concat(buildingOutputs).Concat(sinkInputs).Concat(sourceOutputs).ToImmutableList();

            for (int i = 0; i < 4; i++)
            {
                result = result.Modify(1);
            }

            return(result);
        }
Exemplo n.º 2
0
 public Tuple <SolutionParameters, Searchspace, double> CreateRandom()
 {
     for (int i = 0; i < 32; i++)
     {
         var guess = SolutionParameters.FromFactory(_random.Next(10, 28), _random.Next(10, 28), Factory);
         try
         {
             var solution = GenerateSolution(guess);
             var cost     = Grader.CostForSolution(solution);
             return(new Tuple <SolutionParameters, Searchspace, double>(guess, solution, cost));
         }
         catch (InvalidOperationException) { }
         catch (IndexOutOfRangeException) { }
     }
     return(null);
 }
Exemplo n.º 3
0
        public static IEnumerable <RoutingCoordinate> BuildingToPlaceables(IStep step, SolutionParameters parameters)
        {
            if (step is ProductionStep)
            {
                var building = step as ProductionStep;
                var physical = new ProductionBuilding(building.Recipe, building.Amount, building.Building, parameters.BuildingPositions[building].Item1, parameters.BuildingPositions[building].Item2);
                for (int x = 0; x < physical.Size.X; x++)
                {
                    for (int y = 0; y < physical.Size.Y; y++)
                    {
                        yield return(new RoutingCoordinate(physical.Position + new Vector2(x, y), RoutingCoordinate.CoordinateType.Inserter, BuildingRotation.North));
                    }
                }
                yield break;
            }

            if (step is SourceStep)
            {
                var pos      = parameters.SourcePositions[step as SourceStep];
                var rotation = InwardDirectionForEdge(pos, new Vector2(parameters.Width, parameters.Height));
                yield return(new RoutingCoordinate(pos, RoutingCoordinate.CoordinateType.Belt, rotation));

                yield break;
            }

            if (step is SinkStep)
            {
                var pos      = parameters.SinkPositions[step as SinkStep];
                var rotation = InwardDirectionForEdge(pos, new Vector2(parameters.Width, parameters.Height)).Invert();
                yield return(new RoutingCoordinate(pos, RoutingCoordinate.CoordinateType.Belt, rotation));

                yield break;
            }
        }
Exemplo n.º 4
0
        public static IEnumerable <RoutingCoordinate> BuildingToPipes(IStep step, SolutionParameters parameters, Item item)
        {
            var sourceStep = step as SourceStep;

            if (sourceStep != null)
            {
                var pos      = parameters.SourcePositions[sourceStep];
                var rotation = InwardDirectionForEdge(pos, new Vector2(parameters.Width, parameters.Height));
                yield return(new RoutingCoordinate(pos, RoutingCoordinate.CoordinateType.PipeToGround, rotation));
            }

            var sinkStep = step as SinkStep;

            if (sinkStep != null)
            {
                var pos      = parameters.SinkPositions[sinkStep];
                var rotation = InwardDirectionForEdge(pos, new Vector2(parameters.Width, parameters.Height));
                yield return(new RoutingCoordinate(pos, RoutingCoordinate.CoordinateType.PipeToGround, rotation));
            }

            var productionStep = step as ProductionStep;

            if (productionStep != null)
            {
                List <FluidBox>   boxes;
                List <ItemAmount> items;
                var productionBuilding = new ProductionBuilding(productionStep.Recipe, productionStep.Amount, productionStep.Building,
                                                                parameters.BuildingPositions[productionStep].Item1, parameters.BuildingPositions[productionStep].Item2);

                if (productionStep.Recipe.Ingredients.Where((i) => i.Item == item).Any())
                {
                    boxes = productionBuilding.FluidBoxes.Where((b) => !b.IsOutput).ToList();
                    items = productionBuilding.Recipe.Ingredients.ToList();
                }
                else
                {
                    boxes = productionBuilding.FluidBoxes.Where((b) => b.IsOutput).ToList();
                    items = productionBuilding.Recipe.Results.ToList();
                }
                for (int i = 0; i < boxes.Count; i++)
                {
                    var matchingIngredient = items[Math.Min(i, items.Count - 1)];
                    if (matchingIngredient.Item != item)
                    {
                        continue;
                    }

                    var box = boxes[i];

                    for (int d = 0; d < 4; d++)
                    {
                        var dir       = (BuildingRotation)d;
                        var offsetDir = box.Position + dir.ToVector();
                        if (offsetDir.Clamp(productionBuilding.Size - Vector2.One) == offsetDir)
                        {
                            yield return(new RoutingCoordinate(offsetDir + productionBuilding.Position, RoutingCoordinate.CoordinateType.PipeToGround, dir.Invert()));
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
        public Searchspace GenerateSolution(SolutionParameters parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            var result = new Searchspace(new Vector2(parameters.Width, parameters.Height));

            var buildings = parameters.BuildingPositions.Select((kvp) => new ProductionBuilding(kvp.Key.Recipe, kvp.Key.Amount, kvp.Key.Building, kvp.Value.Item1, kvp.Value.Item2));

            foreach (var building in buildings)
            {
                result = result.AddComponent(building);
            }

            var belts = new Dictionary <Item, List <RoutingCoordinate> >();
            List <Tuple <IStep, Item, bool> > todo = parameters.Connections.ToList();

            while (todo.Count != 0)
            {
                Preview = result;

                var connection = todo[0];
                todo.RemoveAt(0);

                var isDestination = connection.Item3;

                var prev = result;

                if (belts.ContainsKey(connection.Item2))
                {
                    IEnumerable <RoutingCoordinate> sources      = new RoutingCoordinate[] { };
                    IEnumerable <RoutingCoordinate> destinations = new RoutingCoordinate[] { };

                    //TODO: fix itemAmount
                    //TODO: fix fluids
                    if (connection.Item2.ItemType == ItemType.Solid)
                    {
                        if (isDestination)
                        {
                            sources      = belts[connection.Item2];
                            destinations = BuildingToPlaceables(connection.Item1, parameters);
                        }
                        else
                        {
                            sources      = BuildingToPlaceables(connection.Item1, parameters);
                            destinations = belts[connection.Item2];
                        }

                        result = SolidRouter.Route(new ItemAmount(connection.Item2, 1), result, sources, destinations);
                    }
                }
                else
                {
                    var firstMatching = todo.Where((t) => t.Item2 == connection.Item2 && t.Item3 != connection.Item3).First();
                    todo.Remove(firstMatching);
                    var both = new Tuple <IStep, Item, bool>[] { connection, firstMatching };

                    var source      = both.Where((c) => c.Item3 == false).First();
                    var destination = both.Where((c) => c.Item3 == true).First();

                    if (connection.Item2.ItemType == ItemType.Solid)
                    {
                        var sources      = BuildingToPlaceables(source.Item1, parameters);
                        var destinations = BuildingToPlaceables(destination.Item1, parameters);
                        result = SolidRouter.Route(new ItemAmount(connection.Item2, 1), result, sources, destinations);
                    }

                    if (connection.Item2.ItemType == ItemType.Fluid)
                    {
                        var sources      = BuildingToPipes(source.Item1, parameters, connection.Item2);
                        var destinations = BuildingToPipes(destination.Item1, parameters, connection.Item2);
                        result = FluidRouter.Route(new ItemAmount(connection.Item2, 1), result, sources, destinations);
                    }
                }

                if (!belts.ContainsKey(connection.Item2))
                {
                    belts[connection.Item2] = new List <RoutingCoordinate>();
                }
                belts[connection.Item2].AddRange(RoutesToCoords(prev, result));
            }

            return(result);
        }