Example #1
0
/**
 * Function performing a search around a center tile and going outward, thus in circle.
 * Although it really is a square search...
 * Every tile will be tested by means of the callback function proc,
 * which will determine if yes or no the given tile meets criteria of search.
 * @param tile to start the search from. Upon completion, it will return the tile matching the search
 * @param size: number of tiles per side of the desired search area
 * @param proc: callback testing function pointer.
 * @param user_data to be passed to the callback function. Depends on the implementation
 * @return result of the search
 * @pre proc != NULL
 * @pre size > 0
 */

        public static bool CircularTileSearch <T>(ref TileIndex tile, uint size, TestTileOnSearchProc <T> proc, T userData)
        {
            if (proc == null)
            {
                throw new ArgumentNullException(nameof(proc));
            }
            if (size <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(size), "Must be greater than zero");
            }

            if (size % 2 == 1)
            {
                /* If the length of the side is uneven, the center has to be checked
                 * separately, as the pattern of uneven sides requires to go around the center */
                if (proc(ref tile, userData))
                {
                    return(true);
                }

                /* If tile test is not successful, get one tile up,
                 * ready for a test in first circle around center tile */
                tile = TILE_ADD(tile, (uint)(int)TileOffsByDir(Direction.DIR_N));
                return(CircularTileSearch(ref tile, size / 2, 1, 1, proc, userData));
            }
            else
            {
                return(CircularTileSearch(ref tile, size / 2, 0, 0, proc, userData));
            }
        }
Example #2
0
/**
 * Generalized circular search allowing for rectangles and a hole.
 * Function performing a search around a center rectangle and going outward.
 * The center rectangle is left out from the search. To do a rectangular search
 * without a hole, set either h or w to zero.
 * Every tile will be tested by means of the callback function proc,
 * which will determine if yes or no the given tile meets criteria of search.
 * @param tile to start the search from. Upon completion, it will return the tile matching the search.
 *  This tile should be directly north of the hole (if any).
 * @param radius How many tiles to search outwards. Note: This is a radius and thus different
 *                from the size parameter of the other CircularTileSearch function, which is a diameter.
 * @param w the width of the inner rectangle
 * @param h the height of the inner rectangle
 * @param proc callback testing function pointer.
 * @param user_data to be passed to the callback function. Depends on the implementation
 * @return result of the search
 * @pre proc != NULL
 * @pre radius > 0
 */

        public static bool CircularTileSearch <T>(ref TileIndex tile, uint radius, uint w, uint h, TestTileOnSearchProc <T> proc,
                                                  T userData)
        {
            if (proc == null)
            {
                throw new ArgumentNullException(nameof(proc));
            }
            if (radius <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(radius), "Must be greater than zero");
            }

            uint x = TileX(tile) + w + 1;
            uint y = TileY(tile);

            uint[] extent = new uint[(int)DiagDirection.DIAGDIR_END] {
                w, h, w, h
            };

            for (uint n = 0; n < radius; n++)
            {
                for (var dir = (int)DiagDirection.DIAGDIR_BEGIN; dir < (int)DiagDirection.DIAGDIR_END; dir++)
                {
                    /* Is the tile within the map? */
                    for (uint j = extent[dir] + n * 2 + 1; j != 0; j--)
                    {
                        if (x < MapSizeX() && y < MapSizeY())
                        {
                            TileIndex t = TileXY(x, y);
                            /* Is the callback successful? */
                            if (proc(ref t, userData))
                            {
                                /* Stop the search */
                                tile = t;
                                return(true);
                            }
                        }

                        /* Step to the next 'neighbour' in the circular line */
                        x += (uint)_tileoffs_by_diagdir[dir].x;
                        y += (uint)_tileoffs_by_diagdir[dir].y;
                    }
                }
                /* Jump to next circle to test */
                x += (uint)_tileoffs_by_dir[(int)Direction.DIR_W].x;
                y += (uint)_tileoffs_by_dir[(int)Direction.DIR_W].y;
            }

            tile = TileConstants.INVALID_TILE;
            return(false);
        }