Created
April 14, 2020 11:27
-
-
Save atsapura/1a3285d449d71474072b13cbfbecb23e to your computer and use it in GitHub Desktop.
Hex grid using cubical coordinates.
This file contains 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 characters
module HexGrid = | |
[<Struct>] | |
type HexId = | |
{ | |
X: int | |
Y: int | |
Z: int | |
} | |
with | |
member this.Sum = this.X + this.Y + this.Z | |
[<RequireQualifiedAccess>] | |
module HexId = | |
let addX id x = { id with X = id.X + x } | |
let addY id y = { id with Y = id.Y + y } | |
let addZ id z = { id with Z = id.Z + z } | |
[<Struct>] | |
type TileId = private TileId of HexId | |
with | |
member this.Value = let (TileId v) = this in v | |
static member Center = | |
TileId { X = 0; Y = 0; Z = 0 } | |
static member create (hexId: HexId) = | |
if hexId.Sum = 0 then | |
TileId hexId |> Some | |
else None | |
let (|TileId|) id = let (TileId v) = id in v | |
[<Struct>] | |
type VertixId = private VertixId of HexId | |
with | |
member this.Value = let (VertixId v) = this in v | |
static member create (hexId: HexId) = | |
if abs hexId.Sum = 1 then | |
VertixId hexId |> Some | |
else None | |
let (|VertixId|) id = let (VertixId v) = id in v | |
let withinRadius radius (TileId id) = | |
abs id.X <= radius && abs id.Y <= radius && abs id.Z <= radius | |
let private allVariants (a, b, c) = | |
seq { | |
{ X = a; Y = b; Z = c } | |
{ X = b; Y = c; Z = a } | |
{ X = c; Y = a; Z = b } | |
} | |
let ringTiles distance = | |
seq { | |
for i in 0 .. distance do | |
yield! allVariants (-i, i - distance, distance) | |
yield! allVariants (i, distance - i, -distance) | |
} | |
|> Seq.distinct | |
|> Seq.map TileId | |
let neighbours maxRadius (TileId id) = | |
seq { | |
TileId { id with X = id.X + 1; Y = id.Y - 1 } | |
TileId { id with X = id.X - 1; Y = id.Y + 1 } | |
TileId { id with Z = id.Z + 1; Y = id.Y - 1 } | |
TileId { id with Z = id.Z - 1; Y = id.Y + 1 } | |
TileId { id with X = id.X + 1; Z = id.Z - 1 } | |
TileId { id with X = id.X - 1; Z = id.Z + 1 } | |
} | |
|> Seq.filter (withinRadius maxRadius) | |
let vertices (TileId id) = | |
seq { | |
HexId.addX id 1 |> VertixId | |
HexId.addX id -1 |> VertixId | |
HexId.addY id 1 |> VertixId | |
HexId.addY id -1 |> VertixId | |
HexId.addZ id 1 |> VertixId | |
HexId.addZ id -1 |> VertixId | |
} | |
let adjustingTiles maxRadius (VertixId id) = | |
match id.Sum with | |
| -1 -> | |
seq { | |
HexId.addX id 1 |> TileId | |
HexId.addY id 1 |> TileId | |
HexId.addZ id 1 |> TileId | |
} | |
| 1 -> | |
seq { | |
HexId.addX id -1 |> TileId | |
HexId.addY id -1 |> TileId | |
HexId.addZ id -1 |> TileId | |
} | |
| _ -> Seq.empty | |
|> Seq.filter (withinRadius maxRadius) | |
let generateField radius = | |
seq { | |
TileId.Center | |
for i in 1 .. radius do | |
yield! ringTiles i | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment