/* Returns index corresponding to input coordinates, or -1 if invalid */ public static int IndexFromCoordinates(this HexParameters P, HexCoordinates C) { if (P.OutOfBounds(C)) { return(-1); } int i = 0; int w = P.A; int offset = 0; int y = 0; while (y < C.Y) { y++; i += w; if (y >= P.B) { w--; offset++; } if (y < P.C) { w++; } } i += C.X - offset; return(i); }
public static bool OutOfBounds(this HexParameters P, HexParameters Q, HexCoordinates offset) { HexParameters S = P - Q; HexCoordinates fit = new HexCoordinates(0, 0); int a = S.A, b = S.B, c = S.C; while (a > 0 && b > 0 && c <= 0) { a--; b--; c++; } while (a > 0 && b <= 0 && c > 0) { a--; b++; c--; fit = fit.Shift(1, 0); } while (a <= 0 && b > 0 && c > 0) { a++; b--; c--; fit = fit.Shift(0, 1); } S = new HexParameters(a, b, c); if (!ValidParameters(S)) { return(true); } return(S.OutOfBounds(offset + fit)); }
/* Finds valid coordinate from input coordinate */ public static HexCoordinates FindInBounds(this HexParameters P, HexCoordinates C) { if (!ValidParameters(P)) { return(C); } HexCoordinates c = C; int h = P.Height(); while (P.OutOfBounds(c)) { if (c.Y < 0) { c = c.Shift(0, 1); } else if (c.Y >= h) { c = c.Shift(0, -1); } else if (c.X < 0 || c.X - c.Y + P.B <= 0) { c = c.Shift(1, 0); } else { c = c.Shift(-1, 0); } } return(c); }
/* Build array of HexCoordinates corresponding to a convex grid * First cell is (0,0); builds left-to-right, top-to-bottom */ public static HexCoordinates[] BuildHexGrid(HexParameters P) { int gridSize = P.GridSize(); HexCoordinates[] coordinates = new HexCoordinates[gridSize]; int i = 0; int w = P.A; int h = P.Height(); int offset = 0; int y = 0; while (y < h) { for (int x = 0; x < w; x++) { coordinates[i++] = new HexCoordinates(x + offset, y); } y++; if (y >= P.B) { w--; offset++; } if (y < P.C) { w++; } } return(coordinates); }
/* Returns true if coordinates C are invalid for grid size P */ public static bool OutOfBounds(this HexParameters P, HexCoordinates C) { int w = P.A; int h = P.Height(); if (C.Y < 0 || C.Y >= h) { return(true); } int offset = 0; int y = 0; while (y < C.Y) { y++; if (y >= P.B) { w--; offset++; } if (y < P.C) { w++; } } if (C.X < offset || C.X >= w + offset) { return(true); } return(false); }
public static bool OutOfBounds(this HexParameters P, HexCoordinates[] listC, HexCoordinates offset) { foreach (HexCoordinates C in listC) { if (P.OutOfBounds(C + offset)) { return(true); } } return(false); }
/* Fit a subgrid of size Q into a grid of size P */ public static HexParameters FitRange(this HexParameters P, HexParameters Q) { HexParameters S = P - Q; int a = S.A, b = S.B, c = S.C; while (a > 0 && b > 0 && c <= 0) { a--; b--; c++; } while (a > 0 && b <= 0 && c > 0) { a--; b++; c--; } while (a <= 0 && b > 0 && c > 0) { a++; b--; c--; } return(new HexParameters(a, b, c)); }
/* Rotated parameters */ public static HexParameters Rotate(this HexParameters P, int r) { HexParameters p = P; if (r > 0) { for (int i = 0; i < (r % 3); i++) { p = new HexParameters(p.B, p.C, p.A); } } else if (r < 0) { for (int i = 0; i < (-r % 3); i++) { p = new HexParameters(p.C, p.A, p.B); } } return(p); }
public static HexCoordinates FitOffset(this HexParameters P, HexParameters Q) { HexParameters S = P - Q; HexCoordinates fit = new HexCoordinates(0, 0); int a = S.A, b = S.B, c = S.C; while (a > 0 && b > 0 && c <= 0) { a--; b--; c++; } while (a > 0 && b <= 0 && c > 0) { a--; b++; c--; fit = fit.Shift(1, 0); } while (a <= 0 && b > 0 && c > 0) { a++; b--; c--; fit = fit.Shift(0, 1); } return(fit); }
/* Returns true if subgrid of size Q does not fit within grid size P */ public static bool OutOfBounds(this HexParameters P, HexParameters Q) { return(P.OutOfBounds(Q, new HexCoordinates(0, 0))); }
/* Returns true if all parameters are positive */ public static bool ValidParameters(HexParameters P) { return(P.A > 0 && P.B > 0 && P.C > 0); }
/* Number of cells in a grid */ public static int GridSize(this HexParameters P) { return(P.A * (P.B + P.C - 1) + (P.B - 1) * (P.C - 1)); }
/* Number of rows in a grid */ public static int Height(this HexParameters P) { return(P.B + P.C - 1); }
static public bool orthoXZ = false; // false = XY, true = XZ public static HexCoordinates MoveInBounds(this HexParameters P, HexCoordinates C, OrthoDirection d) { HexCoordinates[] neighbors; switch (d) { case OrthoDirection.N: if (orthoXZ) { neighbors = new HexCoordinates[] { C.Neighbor(HexDirection.NW), C.Neighbor(HexDirection.NE) }; } else { neighbors = new HexCoordinates[] { C.Neighbor(HexDirection.NE), C.Neighbor(HexDirection.NW) }; } break; case OrthoDirection.E: neighbors = new HexCoordinates[] { C.Neighbor(HexDirection.E), C.Neighbor(HexDirection.SE), C.Neighbor(HexDirection.NE) }; break; case OrthoDirection.S: if (orthoXZ) { neighbors = new HexCoordinates[] { C.Neighbor(HexDirection.SE), C.Neighbor(HexDirection.SW) }; } else { neighbors = new HexCoordinates[] { C.Neighbor(HexDirection.SW), C.Neighbor(HexDirection.SE) }; } break; case OrthoDirection.W: neighbors = new HexCoordinates[] { C.Neighbor(HexDirection.W), C.Neighbor(HexDirection.NW), C.Neighbor(HexDirection.SW) }; break; default: neighbors = new HexCoordinates[0]; break; } foreach (HexCoordinates N in neighbors) { if (!P.OutOfBounds(N)) { return(N); } } return(C); }