コード例 #1
0
        public double CostForSolution(Searchspace state)
        {
            double cost = 0;

            cost += state.Size.X * state.Size.Y * AreaCost;

            foreach (var production in state.Buildings)
            {
                foreach (var collision in state.CalculateCollisions(production.Position, production.Size))
                {
                    if (collision == production)
                    {
                        continue;
                    }
                    if (collision is ProductionBuilding)
                    {
                        cost += ProductionCollisionCost;
                    }
                }
            }

            foreach (var route in state.Routes)
            {
                cost += CostForBuilding(state, route.Step);
            }
            return(cost);
        }
コード例 #2
0
        public Searchspace Route(ItemAmount item, Searchspace space, IEnumerable <RoutingCoordinate> sources, IEnumerable <RoutingCoordinate> destinations)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            if (destinations == null)
            {
                throw new ArgumentNullException("destinations");
            }

            AStar <FluidRouteState> star = new AStar <FluidRouteState>();

            star.StateGenerator    = (s) => s.NextStates(Grader.CostForBuilding, PipeToGround, Pipe);
            star.EndStateValidator = ValidateEndState;

            foreach (var dest in destinations)
            {
                star.AddDestination(new RoutingCoordinate(dest.Position, dest.State, dest.Rotation.Invert()));
            }

            foreach (var source in sources)
            {
                var startBuilding = new VirtualFlowStep(item, PipeToGround, source.Position, source.Rotation.Invert());
                var startState    = new FluidRouteState(startBuilding, 0, source.Position, space, Depth.None, source.Rotation, true);
                star.AddState(startState);
            }

            while (!star.Step())
            {
            }

            return(star.EndState.Space);
        }
コード例 #3
0
 public SolidRouteState(IPhysicalBuilding building, double cost, Vector2 position, Searchspace space, RoutingCoordinate.CoordinateType transportState, Depth depth = Depth.None, BuildingRotation direction = BuildingRotation.North, int undergroundLength = 0)
 {
     _building          = building;
     _cost              = cost;
     _position          = position;
     _space             = space;
     _depth             = depth;
     _direction         = direction;
     _undergroundLength = undergroundLength;
     _transportState    = transportState;
 }
コード例 #4
0
 public FluidRouteState(IPhysicalBuilding building, double cost, Vector2 position, Searchspace space, Depth depth = Depth.None, BuildingRotation direction = BuildingRotation.North, bool hasJustSurfaced = false, int undergroundLength = 0)
 {
     _building          = building;
     _cost              = cost;
     _position          = position;
     _space             = space;
     _depth             = depth;
     _direction         = direction;
     _hasJustSurfaced   = hasJustSurfaced;
     _undergroundLength = undergroundLength;
 }
コード例 #5
0
        private IEnumerable <RoutingCoordinate> RoutesToCoords(Searchspace previous, Searchspace now)
        {
            var newRoutes = now.Routes.Skip(previous.Routes.Count);

            foreach (var route in newRoutes)
            {
                if (route.Step is Belt)
                {
                    yield return(new RoutingCoordinate(route.Position, RoutingCoordinate.CoordinateType.Splitter, route.Step.Rotation));
                }
            }
        }
コード例 #6
0
        public bool Equals(Searchspace other)
        {
            if (other == null)
            {
                return(false);
            }

            if (other._size != _size)
            {
                return(false);
            }

            var otherBuildings = other.Buildings.OrderBy((b) => b.GetHashCode());

            return(otherBuildings.SequenceEqual(Buildings.OrderBy((b) => b.GetHashCode())));
        }
コード例 #7
0
        public Searchspace AddRoute(FlowBuilding building)
        {
            var result = new Searchspace(Size, _components, _routes.Add(new CollisionBox <FlowBuilding>(building)), _grid);

            for (int x = 0; x < building.Size.X; x++)
            {
                for (int y = 0; y < building.Size.Y; y++)
                {
                    var xpos = x + (int)building.Position.X;
                    var ypos = y + (int)building.Position.Y;
                    if (xpos >= 0 && ypos >= 0 && xpos < Size.X && ypos < Size.Y)
                    {
                        result._grid[xpos, ypos] = _grid[xpos, ypos].Add(building);
                    }
                }
            }

            return(result);
        }
コード例 #8
0
        public double CostForBuilding(Searchspace state, IPhysicalBuilding building)
        {
            if (building == null)
            {
                throw new ArgumentNullException("building");
            }

            double cost = building.Size.X * building.Size.Y * LandUseCost;

            if (building.Position.X <= 0 && building.Rotation != BuildingRotation.West && building.Rotation != BuildingRotation.East)
            {
                cost += EdgeUseCost;
            }
            if (building.Position.Y <= 0 && building.Rotation != BuildingRotation.North && building.Rotation != BuildingRotation.South)
            {
                cost += EdgeUseCost;
            }
            if (building.Position.X >= state.Size.X - building.Size.X && building.Rotation != BuildingRotation.East && building.Rotation != BuildingRotation.West)
            {
                cost += EdgeUseCost;
            }
            if (building.Position.Y >= state.Size.Y - building.Size.Y && building.Rotation != BuildingRotation.South && building.Rotation != BuildingRotation.North)
            {
                cost += EdgeUseCost;
            }

            var accountable = building as IAccountableBuilding;

            if (accountable != null)
            {
                cost += accountable.CalculateCost(state, this);
            }

            if (CostLookup.ContainsKey(building.Building.Name))
            {
                cost += CostLookup[building.Building.Name];
            }

            return(cost);
        }
コード例 #9
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);
        }
コード例 #10
0
        /// <summary>
        /// Attempts to route from the start states to the destination states. The given states are both lists, but only one state from each list will be selected for the final routing.
        /// </summary>
        /// <param name="item">How much to route.</param>
        /// <param name="space">The initialstate from which the routing starts.</param>
        /// <param name="startPositions">The list of starting states. Only one will be used.</param>
        /// <param name="destinations">The list of desired destination states. Only one will be reached.</param>
        /// <returns>The solution state found after routing</returns>
        public Searchspace Route(ItemAmount item, Searchspace space, IEnumerable <RoutingCoordinate> startPositions, IEnumerable <RoutingCoordinate> destinations)
        {
            if (startPositions == null)
            {
                throw new ArgumentNullException("startPositions");
            }
            if (destinations == null)
            {
                throw new ArgumentNullException("destinations");
            }

            AStar <SolidRouteState> star = new AStar <SolidRouteState>();

            star.StateGenerator    = (s) => s.NextStates(Grader.CostForBuilding, Belt, BeltGroundNormal, BeltGroundFast, BeltGroundExpress, Inserter, LongInserter, FastInserter, Splitter);
            star.EndStateValidator = ValidateEndState;

            foreach (var dest in destinations)
            {
                star.AddDestination(dest);
            }

            foreach (var position in startPositions)
            {
                switch (position.State)
                {
                case RoutingCoordinate.CoordinateType.Belt:
                    var startBuilding = new Belt(item, Belt, position.Position, position.Rotation);
                    var tmpSpace1     = space.AddRoute(startBuilding);
                    var startState    = new SolidRouteState(startBuilding, 0, position.Position, tmpSpace1, RoutingCoordinate.CoordinateType.Belt, Depth.None, position.Rotation);
                    star.AddState(startState);
                    break;

                case RoutingCoordinate.CoordinateType.PlacedItem:
                case RoutingCoordinate.CoordinateType.Inserter:
                    var startPlacedBuilding = new PlacedItem(item, position.Position);
                    var tmpSpace2           = space.AddRoute(startPlacedBuilding);
                    var startPlacedState    = new SolidRouteState(startPlacedBuilding, 0, position.Position, tmpSpace2, RoutingCoordinate.CoordinateType.PlacedItem);
                    star.AddState(startPlacedState);
                    break;

                case RoutingCoordinate.CoordinateType.Splitter:
                    var offsets = new BuildingRotation[] {
                        BuildingRotation.West,
                        BuildingRotation.North,
                        BuildingRotation.West,
                        BuildingRotation.North,
                    };

                    var offsetDir      = offsets[(int)position.Rotation];
                    var startSplitter1 = new Splitter(item, Splitter, position.Position, position.Rotation);
                    var startSplitter2 = new Splitter(item, Splitter, position.Position + offsetDir.ToVector(), position.Rotation);
                    var space1         = space.AddRoute(startSplitter1);
                    var space2         = space.AddRoute(startSplitter2);
                    var state1         = new SolidRouteState(startSplitter1, 0, position.Position - offsetDir.ToVector(), space1, RoutingCoordinate.CoordinateType.Belt, Depth.None, position.Rotation);
                    var state2         = new SolidRouteState(startSplitter2, 0, position.Position + offsetDir.ToVector(), space2, RoutingCoordinate.CoordinateType.Belt, Depth.None, position.Rotation);
                    var before         = space.CalculateCollisions(position.Position - position.Rotation.ToVector()).OfType <Belt>()
                                         .Where((b) => b.Item.Item == item.Item)
                                         .Where((b) => b.Rotation == position.Rotation);
                    var after = space.CalculateCollisions(position.Position + position.Rotation.ToVector()).OfType <Belt>()
                                .Where((b) => b.Item.Item == item.Item)
                                .Where((b) => b.Rotation == position.Rotation);

                    if (before.Any() && after.Any())
                    {
                        star.AddState(state1);
                        star.AddState(state2);
                    }

                    var startPlacedBuilding2 = new PlacedItem(item, position.Position);
                    var tmpSpace3            = space.AddRoute(startPlacedBuilding2);
                    var startPlacedState2    = new SolidRouteState(startPlacedBuilding2, 0, position.Position, tmpSpace3, RoutingCoordinate.CoordinateType.PlacedItem);
                    star.AddState(startPlacedState2);
                    break;
                }
            }

            while (!star.Step())
            {
            }

            return(star.EndState.Space);
        }