示例#1
0
        /** <summary>
         * Given some coordinates, find all sides of the given tile such that the neighbour
         * on that side, and all subsequent neighbours in a contiguous clockwise rotation
         * for n turns, are valid for placement.
         * </summary>
         * <remarks>
         * If more sides are requested than the maximum number of adjacent tiles allows
         * (6, for a hexagonal grid), the maximum number of sides will be used as a ceiling.
         * </remarks>
         * <param name="coords">The coordinates (start point) to search from.</param>
         * <param name="n">The number of contiguous sides to find.</param>
         * <return>A list of all sides which have <paramref name="n"/> clockwise contiguous valid neighbours.</return>
         */
        private List <Hex.Side> FindNContiguousValidSides(Coords coords, int n)
        {
            // Can't have more than the max number of sides
            if (n > Hex.SIDES)
            {
                n = Hex.SIDES;
            }
            List <Hex.Side> goodSides = new List <Hex.Side>();

            // Filter out any invalid sides
            Dictionary <Hex.Side, Coords> adj = GetFilteredAdjacency(coords);

            foreach (Hex.Side side in adj.Keys)
            {
                int      count     = 1;
                Hex.Side checkSide = Hex.RotateSideClockwise(side);
                while (adj.ContainsKey(side) && count < Hex.SIDES)
                {
                    count++;
                    checkSide = Hex.RotateSideClockwise(side);
                }
                if (count >= n)
                {
                    goodSides.Add(side);
                }
            }

            return(goodSides);
        }
示例#2
0
        public void Extend(Hex.Side side, Coords coords)
        {
            RiverSegment newSeg = new RiverSegment(this, coords);

            LastSeg.ExitSide    = side;
            newSeg.EntrySide    = Hex.OppositeSide(side);
            newSeg.PrevSegment  = LastSeg;
            LastSeg.NextSegment = newSeg;
            LastSeg             = newSeg;
        }
示例#3
0
 /**
  * <summary>
  * Given two Coords, determines if they are adjacent and, if so, on which
  * side.
  * </summary>
  * <param name="reference">
  * The Coords of the reference Hex to check adjacency. This is the Hex
  * that the returned side will be relative to.
  * </param>
  * <param name="check">The Coordsto check adjacency against.</param>
  * <returns>
  * The Hex.Side of the Hex at <paramref name="reference"/> that
  * the Hex at <paramref name="check"/> is adjacent to, if it is.
  * Returns Hex.Side.Nil otherwise.
  * </returns>
  */
 public Hex.Side GetAdjacentSide(Coords reference, Coords check)
 {
     for (Hex.Side side = Hex.Side.North; side < Hex.Side.Nil; side++)
     {
         if (GetAdjacentCoords(reference, side) == check)
         {
             return(side);
         }
     }
     return(Hex.Side.Nil);
 }
示例#4
0
        /**
         * <summary>
         * Gets a Dictionary of all Coords adjacent to specified Coords on the map.
         * The keys of the Dictionary are the sides of the adjacency -- that is,
         * the side of the Hex at the given Coords that the value at that point in
         * the Dictionary is specifically adjacent to (<see cref="Hex.Side"/>).
         * </summary>
         * <remarks>
         * Handles wrap-around adjacency.
         * </remarks>
         * <param name="coords">The Coords to query.</param>
         * <returns>
         * Dictionary of all Coords adjacent to <paramref name="coords"/>, keyed
         * to the hex side on which they are adjacent.
         * </returns>
         */
        public Dictionary <Hex.Side, Coords> GetAllAdjacentCoords(Coords coords)
        {
            Dictionary <Hex.Side, Coords> adjCoords = new Dictionary <Hex.Side, Coords>();

            for (Hex.Side side = 0; side < Hex.Side.Nil; side++)
            {
                Coords maybeCoords = GetAdjacentCoords(coords, side);
                if (!maybeCoords.invalid)
                {
                    adjCoords.Add(side, maybeCoords);
                }
            }

            return(adjCoords);
        }
示例#5
0
        // Helper method to get the coordinates of the middle of a given side from origin coords
        // (upper-left point of the hexagon)
        private Point GetCoordsOfSideMidpoint(Double oriX, Double oriY, Hex.Side side, Double scale = DEFAULT_SCALE)
        {
            Point offset = GetHexagonOffsets();
            Point rv     = new Point(oriX, oriY);

            switch (side)
            {
            case Hex.Side.North:
                rv.X += (scale / 2.0);
                break;

            case Hex.Side.Northeast:
                rv.X += scale;
                rv.X += (offset.X / 2.0);
                rv.Y += (offset.X / 2.0);
                break;

            case Hex.Side.Northwest:
                rv.X -= (offset.X / 2.0);
                rv.Y += (offset.X / 2.0);
                break;

            case Hex.Side.South:
                rv.X += (scale / 2.0);
                rv.Y += (scale * 2);
                break;

            case Hex.Side.Southeast:
                rv.X += scale;
                rv.X += (offset.X / 2.0);
                rv.Y += scale;
                rv.Y += (offset.X / 2.0);
                break;

            case Hex.Side.Southwest:
                rv.X -= (offset.X / 2.0);
                rv.Y += scale;
                rv.Y += (offset.X / 2.0);
                break;

            default:
                break;
            }
            return(rv);
        }
示例#6
0
        private void DrawRivers(Double scale = DEFAULT_SCALE)
        {
            foreach (var river in _world.Rivers)
            {
                RiverSegment seg = river.FirstSeg;
                MapRiver     mr  = new MapRiver();

                mr.Points.Add(CenterPointFromCoords(seg.Location));

                while ((seg.NextSegment != null))
                {
                    if (CoordsWrap(seg.Location, seg.NextSegment.Location))
                    {
                        Point loc       = PointFromCoords(seg.Location);
                        Point exitPoint = GetCoordsOfSideMidpoint(loc.X, loc.Y, (Hex.Side)seg.ExitSide);
                        mr.Points.Add(exitPoint);
                        MapRivers.Add(mr);
                        mr  = new MapRiver();
                        loc = PointFromCoords(seg.NextSegment.Location);
                        Point entryPoint = GetCoordsOfSideMidpoint(loc.X, loc.Y, (Hex.Side)seg.NextSegment.EntrySide);
                        mr.Points.Add(entryPoint);
                    }
                    seg = seg.NextSegment;
                    mr.Points.Add(CenterPointFromCoords(seg.Location));
                }

                if (river.LastSeg.ExitSide != null)
                {
                    Hex.Side exitSide     = (Hex.Side)river.LastSeg.ExitSide;
                    Point    loc          = PointFromCoords(river.LastSeg.Location);
                    Point    sideMidpoint = GetCoordsOfSideMidpoint(loc.X, loc.Y, exitSide);
                    mr.Points.Add(sideMidpoint);
                }

                MapRivers.Add(mr);
            }
        }
示例#7
0
        /**
         * <summary>
         * Given some Coords and a Hex.Side, returns the Coords of the Hex that
         * is adjacent to the Hex at the given Coords on that side.
         * </summary>
         * <param name="coords">Coords of the central Hex to check.</param>
         * <param name="side">Side on which to determine adjacency.</param>
         * <returns>
         * Coords of the Hex adjacent to the hex at
         * <paramref name="coords"/> on <paramref name="side"/>.
         * </returns>
         */
        public Coords GetAdjacentCoords(Coords coords, Hex.Side side)
        {
            int x         = coords.x;
            int y         = coords.y;
            int upShift   = 0;
            int downShift = 0;

            if (x % 2 != 0)
            {
                downShift = 1;
            }
            else
            {
                upShift = -1;
            }

            if (x < 0)
            {
                x = 0;
            }
            if (y < 0)
            {
                y = 0;
            }
            if (x > (Width - 1))
            {
                x = (Width - 1);
            }
            if (y > (Height - 1))
            {
                y = (Height - 1);
            }

            Coords rv = new Coords();

            switch (side)
            {
            case Hex.Side.North:
                rv.x = x;
                rv.y = y - 1;
                break;

            case Hex.Side.Northwest:
                rv.x = x - 1;
                rv.y = y + upShift;
                break;

            case Hex.Side.Northeast:
                rv.x = x + 1;
                rv.y = y + upShift;
                break;

            case Hex.Side.South:
                rv.x = x;
                rv.y = y + 1;
                break;

            case Hex.Side.Southwest:
                rv.x = x - 1;
                rv.y = y + downShift;
                break;

            case Hex.Side.Southeast:
                rv.x = x + 1;
                rv.y = y + downShift;
                break;

            default:
                break;
            }

            if (rv.y < 0 || rv.y > (Height - 1))
            {
                rv.invalid = true;
            }
            if (rv.x < 0)
            {
                rv.x = (Width - 1);
            }
            else if (rv.x > (Width - 1))
            {
                rv.x = 0;
            }

            return(rv);
        }
示例#8
0
 public void Terminate(Hex.Side side)
 {
     LastSeg.ExitSide = side;
 }
示例#9
0
        /** <summary>
         * Expand the given property in the map, within a set of coords predetermined
         * to point to hexes valid for expansion.
         * </summary>
         * <param name="validHexes">List of all coords containing hexes which are valid to expand to.</param>
         * <param name="size">The number of hexes to expand.</param>
         * <return>The list of all coords whose corresponding hexes were modified by this expansion.</return>
         */
        public List <Coords> Expand(List <Coords> validHexes, int size)
        {
            int width  = _map.Width;
            int height = _map.Height;

            _totalHexes = _remainingHexes = size;
            _validHexes = validHexes;

            // list of coords to be expanded out from, but which have not been expanded from yet
            List <Coords> unexpanded = new List <Coords>();
            // list of coords to expand from again
            List <Coords> expandAgain = new List <Coords>();

            List <Coords> rv = new List <Coords>();

            // Select a valid hex at random to start from
            bool placedSeed      = false;
            int  attempts        = 0;
            int  totalValidHexes = validHexes.Count;

            while (!placedSeed &&
                   (attempts < totalValidHexes))
            {
                int    i          = _rand.GenerateInt(totalValidHexes);
                Coords seedCoords = validHexes[i];
                if (CanExpandFirst(seedCoords))
                {
                    placedSeed = ModHex(seedCoords);
                    if (placedSeed)
                    {
                        _remainingHexes--;
                        rv.Add(seedCoords);
                        unexpanded.Add(seedCoords);
                        continue;
                    }
                }
                attempts++;
            }

            while ((_remainingHexes > 0) &&
                   !_finalizeEarly)
            {
                if (unexpanded.Count == 0)
                {
                    if (AllowsReexpansion &&
                        (expandAgain.Count() > 0))
                    {
                        unexpanded = expandAgain;
                    }
                    else
                    {
                        break;
                    }
                }

                // Pick a hex to expand at random from the unexpanded list
                Coords startPoint = unexpanded[_rand.GenerateInt(unexpanded.Count)];
                Dictionary <Hex.Side, Coords> adj = GetFilteredAdjacency(startPoint);

                // Determine at random how many hexes will be affected in this expansion
                // (i.e. how many adjacent hexes we'll attempt to modify in this round)
                int             roll    = RollBaseExpansion(adj.Count + 1) + RollModifier();
                List <Hex.Side> contigs = FindNContiguousValidSides(startPoint, roll);

                if (contigs.Count > 0)
                {
                    Hex.Side placeSide = contigs[_rand.GenerateInt(contigs.Count)];
                    int      count     = 0;

                    // Try to modify as many contiguous hexes as we randomly determined we would
                    while (count < roll)
                    {
                        if (adj.ContainsKey(placeSide))
                        {
                            Coords placeLoc = adj[placeSide];
                            bool   placed   = ModHex(placeLoc);
                            if (placed)
                            {
                                rv.Add(placeLoc);
                                _remainingHexes--;
                                unexpanded.Add(placeLoc);
                            }
                        }
                        placeSide = Hex.RotateSideClockwise(placeSide);
                        count++;
                    }
                }

                // We've now expanded from these coords; remove them from the unexpanded list
                unexpanded.Remove(startPoint);
                // But if there are more adjacent hexes to expand to than we expanded into this round,
                // we can add this hex into the expand-again list
                if (roll < adj.Count)
                {
                    expandAgain.Add(startPoint);
                }
            }

            // Go through all remaining Coords that were not expanded from, and do something with
            // their adjacent hexes, depending on the implementation of FinishAdjacentUnexpanded().
            foreach (Coords remainder in unexpanded)
            {
                Dictionary <Hex.Side, Coords> toGo = GetFilteredAdjacency(remainder);
                foreach (Coords toGoInstance in toGo.Values)
                {
                    FinishAdjacentUnexpanded(toGoInstance);
                }
            }

            return(rv);
        }