/** <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); }
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; }
/** * <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); }
/** * <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); }
// 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); }
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); } }
/** * <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); }
public void Terminate(Hex.Side side) { LastSeg.ExitSide = side; }
/** <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); }