Created
May 5, 2021 01:23
Revisions
-
ftsf created this gist
May 5, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,169 @@ import nico import nico/vec type GridLayout* = enum gridSquare gridHexPointyTop type Grid*[T] = ref object layout*: GridLayout wrapX*: bool wrapY*: bool width*: int height*: int data*: seq[T] default*: T proc set*[T](g: Grid[T], x,y: int, t: T) = if x < 0 or y < 0 or x >= g.width or y >= g.height: return g.data[y * g.width + x] = t proc get*[T](g: Grid[T], x,y: int): T = if x < 0 or y < 0 or x >= g.width or y >= g.height: return default(T) return g.data[y * g.width + x] proc get*[T](g: Grid[T], v: Vec2i): T = return g.get(v.x, v.y) proc set*[T](g: Grid[T], v: Vec2i, t: T) = g.set(v.x, v.y, t) proc `[]`*[T](g: Grid[T], v: Vec2i): T = g.get(v) proc `[]`*[T](g: Grid[T], x,y: int): T = g.data[y * g.width + x] proc `[]`*[T](g: var Grid[T], x,y: int): var T = g.data[y * g.width + x] proc `[]`*[T](g: var Grid[T], v: Vec2i): var T = g.data[v.y * g.width + v.x] proc `[]=`*[T](g: Grid[T], v: Vec2i, t: T) = g.set(v,t) proc `[]=`*[T](g: Grid[T], x,y: int, t: T) = g.set(vec2i(x,y),t) const hexNeighbours = [ [ 0,+1,-1], [+1, 0,-1], [+1,-1, 0], [ 0,-1,+1], [-1, 0,+1], [-1,+1, 0], ] func toHexCoord*(hex: Vec2i): Vec3i = let x = hex.x - (hex.y - (hex.y and 1)) div 2 let z = hex.y let y = -x-z return vec3i(x,y,z) func toOffset*(cube: Vec3i): Vec2i = let col = cube.x + (cube.z - (cube.z and 1)) div 2 let row = cube.z return vec2i(col, row) proc isAdjacent*(g: Grid, a,b: Vec2i): bool = if g.layout == gridSquare: if a.x == b.x: if abs(a.y - b.y) == 1: return true elif g.wrapY and abs(a.y - b.y) == g.height - 1: return true elif a.y == b.y: if abs(a.x - b.x) == 1: return true if g.wrapX and abs(a.x - b.x) == g.width - 1: return true else: let aCube = toHexCoord(a) let bCube = toHexCoord(b) let d = abs(aCube.x - bCube.x) + abs(aCube.y - bCube.y) + abs(aCube.z - bCube.z) if d == 1: return true # TODO handle wrapping return false iterator adjacent*[T](g: Grid[T], v: Vec2i, diagonal = false): Vec2i = case g.layout: of gridSquare: if g.wrapX: yield vec2i(wrap(v.x-1,g.width),v.y) yield vec2i(wrap(v.x+1,g.width),v.y) else: if v.x > 0: yield vec2i(v.x-1,v.y) if v.x < g.width - 1: yield vec2i(v.x+1,v.y) if g.wrapY: yield vec2i(v.x, wrap(v.y-1,g.height)) yield vec2i(v.x, wrap(v.y+1,g.height)) else: if v.y > 0: yield vec2i(v.x,v.y-1) if v.y < g.height - 1: yield vec2i(v.x,v.y+1) if diagonal: if v.x > 0: if v.y > 0: yield vec2i(v.x-1,v.y-1) if v.y < g.height - 1: yield vec2i(v.x-1,v.y+1) if v.x < g.width - 1: if v.y > 0: yield vec2i(v.x+1,v.y-1) if v.y < g.height - 1: yield vec2i(v.x+1,v.y+1) of gridHexPointyTop: let cube = v.toHexCoord() for offset in hexNeighbours: let n = cube + offset let pos = n.toOffset() if pos.x >= 0 and pos.x < g.width and pos.y >= 0 and pos.y < g.height: yield pos proc getNeighbor*(g: Grid, start: Vec2i, dir: Vec3i): Vec2i = if g.layout == gridSquare: return start + dir.xyi else: let startCube = start.toHexCoord() let offset = (startCube + dir).toOffset() return offset iterator items*[T](g: Grid[T]): T = for v in g.data: yield v iterator mitems*[T](g: var Grid[T]): var T = for v in g.data.mitems: yield v iterator pairs*[T](g: Grid[T]): (Vec2i,T) = for y in 0..<g.height: for x in 0..<g.width: yield (vec2i(x,y), g[x,y]) iterator mpairs*[T](g: var Grid[T]): (Vec2i, var T) = for y in 0..<g.height: for x in 0..<g.width: yield (vec2i(x,y), g[x,y]) proc newGrid*[T](w,h: int, layout: GridLayout = gridSquare, default: T = default(T)): Grid[T] = result = new(Grid[T]) result.layout = layout result.width = w result.height = h result.default = default result.data = newSeq[T](w*h) for y in 0..<h: for x in 0..<w: result.set(x,y,default)