/// <summary>
        /// Return build moves around the unit of the selected type and in a specified maximum distance
        /// </summary>
        /// <param name="unit">The unit that will build</param>
        /// <param name="board">The board to build on</param>
        /// <param name="type">The type of unit to build</param>
        /// <param name="distance">The maximum distance to build in</param>
        /// <returns>A list of movement moves that unit can do, of units of type 'type' and in distance 'distance'</returns>
        public static List <Move> BuildAroundMove(this Unit unit, Tile[,] board, UnitType type, int distance)
        {
            List <Move> moves = new List <Move>();

            //Get the 9 tiles around this building
            int xStart = Math.Max(0, unit.px / Tile.TILE_WIDTH - distance);
            int xEnd   = Math.Min(Game.TILES_WIDTH - 1, unit.px / Tile.TILE_WIDTH + distance);
            int yStart = Math.Max(0, unit.py / Tile.TILE_HEIGHT - distance);
            int yEnd   = Math.Min(Game.TILES_HEIGHT - 1, unit.py / Tile.TILE_HEIGHT + distance);

            for (int x = xStart; x <= xEnd; x++)
            {
                for (int y = yStart; y <= yEnd; y++)
                {
                    if (type.CanPlaceOn(board, x, y))
                    {
                        moves.Add(new BuildMove(unit, x, y, type));
                    }
                }
            }

            return(moves);
        }
Beispiel #2
0
        /// <summary>
        /// Get a path to the nearest tile satisfying a TileLookupConstraint. The algorithm used is flood fill, meaning the optimal path is
        /// Gurrenteed.
        /// </summary>
        /// <param name="traveler">The unit type that attempts to travel</param>
        /// <param name="board">The board to search for a path in</param>
        /// <param name="xStart">The beggining position of the path in tiles</param>
        /// <param name="yStart">The beggining position of the path in tiles</param>
        /// <param name="constraint">The TileLookupConstraint object that decides if a tile is good</param>
        /// <returns>A List of ALocations starting at (xStart,yStart) and ending at the nearest tile satisfying the constraint</returns>
        public static List <ALocation> PathToNearestTile(UnitType traveler, Tile[,] board, int xStart, int yStart, TileLookupConstraint constraint)
        {
            ALocation start = new ALocation(xStart, yStart);

            //Current positions to check
            Stack <ALocation> current = new Stack <ALocation>();
            //Next positions to check
            Stack <ALocation> next = new Stack <ALocation>();

            //Start by checking the start
            current.Push(start);

            //Iteration i checks all the tiles in distance 1 from the beggining. Repeat until the maximum path length is reached.
            for (int i = 0; i < MAX_PATH_LENGTH; i++)
            {
                //Check every tile in the current list
                foreach (ALocation test in current)
                {
                    Console.WriteLine("Checking " + test);
                    //Check if the tile satisfies the constraint
                    if (constraint.Check(test.Tile(board)))
                    {
                        //If it does, trace the path using the parent property of each ALocation and return it.
                        Console.WriteLine("Found tile satisfying " + constraint + " in " + test.x + ", " + test.y);
                        List <ALocation> res  = new List <ALocation>();
                        ALocation        curr = test;
                        while (curr != null)
                        {
                            res.Add(curr);
                            curr = curr.parent;
                        }
                        //Clear the flags
                        foreach (Tile t in board)
                        {
                            t.flag = false;
                        }
                        //Return the path
                        res.Reverse();
                        res.RemoveAt(0);
                        return(res);
                    }

                    //If the traveler cannot walk on that tile, stop checking it, it cannot be path of a path.
                    if (!traveler.CanPlaceOn(board, test.x, test.y) && test != start)
                    {
                        continue;
                    }

                    //This tile is not final but may be in the shortest path. Check all tiles adjecent to it.
                    foreach (ALocation l in GetAdjacentSquares(traveler, board, test.x, test.y))
                    {
                        //Only check tiles that weren't checked yet.
                        if (!board[l.x, l.y].flag)
                        {
                            l.parent = test;
                            next.Push(l);

                            //Mark this tile as checked.
                            board[l.x, l.y].flag = true;
                        }
                    }
                }
                //Finished checking current tiles, switch on to the next batch.
                current = next;
                next    = new Stack <ALocation>();
            }
            //If the maximum tile length is reached and no path was found, stop looking, unflag all tiles and return null.
            foreach (Tile t in board)
            {
                t.flag = false;
            }

            return(null);
        }