Class ScyllaHexGrid<TCell>
Dense, array-backed hexagonal grid storing per-cell data of type TCell.
Cells are addressed by HexCoord (axial q, r) with O(1) random access.
The grid covers a rectangular region in axial space defined by
(QMin..QMin+Width-1, RMin..RMin+Height-1).
Unsynchronized by default; use AsSynchronized(object) to obtain a thread-safe wrapper.
Inherited Members
Namespace: Scylla.Core.Structures
Assembly: ScyllaCore.dll
Syntax
public sealed class ScyllaHexGrid<TCell> : IScyllaGrid<HexCoord, TCell>, IScyllaCollection
Type Parameters
| Name | Description |
|---|---|
| TCell | The type of data stored in each grid cell. May be a value or reference type. |
Remarks
All cells are pre-allocated at construction time as a flat TCell array
using row-major (R-major) storage: the flat index for coordinate (q, r) is
(r - RMin) * Width + (q - QMin). Because all cells exist from construction, the
grid is never considered logically empty (IsEmpty always returns
false).
Use the fluent ScyllaHexGrid<TCell>.Builder (obtained via CreateBuilder()) to configure hexagonal bounds, default fill values, or thread safety in a readable chain. Use the constructor directly when parameters are simple and known at compile time.
For grids that store only a sparse subset of cells, use ScyllaSparseHexGrid<TCell> instead, which uses a dictionary and supports unbounded extents.
The grid implements IScyllaGrid<TCoord, TCell> and reports the following
capabilities: SupportsContains | SupportsKeyLookup | SupportsRandomAccess | HasCapacity.
var grid = new ScyllaHexGrid<int>(10, 10, new HexGridLayout(1f, HexOrientation.PointyTop));
grid[new HexCoord(3, 4)] = 42;
var value = grid[new HexCoord(3, 4)]; // 42
Constructors
ScyllaHexGrid(int, int, HexGridLayout, int, int)
Creates a new dense hex grid with the specified dimensions and layout.
The grid covers axial coordinates from (qMin, rMin) to (qMin+width-1, rMin+height-1).
All cells are pre-allocated and initialized to default(TCell).
Declaration
public ScyllaHexGrid(int width, int height, HexGridLayout layout, int qMin = 0, int rMin = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| int | width | The number of columns in the Q direction. Must be at least 1. |
| int | height | The number of rows in the R direction. Must be at least 1. |
| HexGridLayout | layout | The spatial layout used for GridToWorld(HexCoord) and WorldToGrid(Vector2) conversions. |
| int | qMin | The minimum Q value of the grid bounds. Defaults to 0. |
| int | rMin | The minimum R value of the grid bounds. Defaults to 0. |
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
Properties
Capabilities
Gets the feature and capability flags supported by this collection instance.
Declaration
public ScyllaCollectionCapabilities Capabilities { get; }
Property Value
| Type | Description |
|---|---|
| ScyllaCollectionCapabilities | A bitfield of ScyllaCollectionCapabilities flags describing which optional operations the concrete instance supports. The value None indicates that only the base contract (Count, IsEmpty, Clear()) is available. |
Remarks
Use Capabilities for feature detection in place of type-casting. For example:
if ((collection.Capabilities & ScyllaCollectionCapabilities.SupportsPeek) != 0)
{
// safe to call TryPeek through IScyllaCollection<T>
}
Synchronized wrappers cache the capability flags of their inner collection at construction time, so the value returned is stable and does not require synchronization.
See Also
CellCount
Gets the number of populated (logically active) cells in the grid.
Declaration
public int CellCount { get; }
Property Value
| Type | Description |
|---|---|
| int | For dense grids, this always equals Count - every cell slot is pre-allocated and considered populated regardless of its stored value. The value is fixed at construction and never changes. For sparse grids, this equals the number of cells that have been explicitly written via TrySet(TCoord, TCell) and not yet removed. The value may be zero on a freshly created or cleared sparse grid. |
See Also
Count
Gets the number of items currently contained in the collection.
Declaration
public int Count { get; }
Property Value
| Type | Description |
|---|---|
| int | A non-negative integer representing the current element count.
Returns |
Remarks
On unsynchronized collections, Count is not thread-safe and may return a stale
value when accessed concurrently. On synchronized wrappers, reading Count is
protected by the internal lock.
Height
Gets the grid height (number of rows in axial R direction).
Declaration
public int Height { get; }
Property Value
| Type | Description |
|---|---|
| int |
IsEmpty
Always false. A dense grid pre-allocates all cells at construction time and is never considered logically empty; use Fill(TCell) to reset cell values.
Declaration
public bool IsEmpty { get; }
Property Value
| Type | Description |
|---|---|
| bool |
this[HexCoord]
Gets or sets the cell value at the specified coordinate with bounds checking. For a non-throwing alternative, use TryGet(HexCoord, out TCell) or TrySet(HexCoord, TCell).
Declaration
public TCell this[HexCoord coord] { get; set; }
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The axial hex coordinate to access. |
Property Value
| Type | Description |
|---|---|
| TCell |
Exceptions
| Type | Condition |
|---|---|
| IndexOutOfRangeException | Thrown when |
Layout
Gets the layout used for world-space conversion.
Declaration
public HexGridLayout Layout { get; }
Property Value
| Type | Description |
|---|---|
| HexGridLayout |
QMin
Gets the minimum Q value in the grid bounds.
Declaration
public int QMin { get; }
Property Value
| Type | Description |
|---|---|
| int |
RMin
Gets the minimum R value in the grid bounds.
Declaration
public int RMin { get; }
Property Value
| Type | Description |
|---|---|
| int |
SyncRoot
Gets the synchronization root object used to externally coordinate multi-step operations with this collection.
Declaration
public object SyncRoot { get; }
Property Value
| Type | Description |
|---|---|
| object | A non-null object suitable for use with |
Remarks
When this collection is a synchronized wrapper, SyncRoot must be non-null and
stable for the entire lifetime of the wrapper. All internal operations on the wrapper
must lock on this same object. This allows callers to perform atomic multi-step
sequences:
lock (collection.SyncRoot)
{
if (!collection.IsEmpty)
typedCollection.TryRemove(out var item);
}
For unsynchronized collections (SyncRoot == null), callers are responsible for
supplying and consistently applying their own external synchronization mechanism.
A null SyncRoot does not mean the collection is thread-safe;
consult ThreadSafety for the authoritative guarantee.
See Also
ThreadSafety
Gets the thread-safety guarantees provided by this collection instance.
Declaration
public ScyllaCollectionThreadSafety ThreadSafety { get; }
Property Value
| Type | Description |
|---|---|
| ScyllaCollectionThreadSafety | A ScyllaCollectionThreadSafety value indicating whether the collection is unsynchronized, synchronized via a lock, or safe for lock-free concurrent access. Most core implementations return Unsynchronized. Synchronized wrappers return Synchronized. |
Remarks
Always check this property (or SyncRoot) before assuming a collection is
safe for concurrent use. Do not rely solely on the absence of a non-null SyncRoot
to infer thread safety; use this property as the authoritative source.
See Also
Width
Gets the grid width (number of columns in axial Q direction).
Declaration
public int Width { get; }
Property Value
| Type | Description |
|---|---|
| int |
Methods
AsSynchronized(object)
Creates and returns a ScyllaHexGrid<TCell>.SynchronizedScyllaHexGrid wrapper that synchronizes all read and write operations on this grid using a single lock object.
Declaration
public ScyllaHexGrid<TCell>.SynchronizedScyllaHexGrid AsSynchronized(object syncRoot = null)
Parameters
| Type | Name | Description |
|---|---|---|
| object | syncRoot | Optional external lock object to use for synchronization. Pass a shared lock to coordinate across multiple collections atomically. If null, the wrapper creates its own private lock object. |
Returns
| Type | Description |
|---|---|
| ScyllaHexGrid<TCell>.SynchronizedScyllaHexGrid | A ScyllaHexGrid<TCell>.SynchronizedScyllaHexGrid wrapping this grid instance. |
Clear()
Removes all items from the collection and resets it to an empty state.
Declaration
public void Clear()
Remarks
Implementations that store reference-type elements should null out internal slots after
clearing to avoid retaining object references and preventing garbage collection.
After Clear returns, Count must be 0 and
IsEmpty must be true.
On synchronized wrappers this operation is protected by the collection's internal lock. On unsynchronized collections, callers are responsible for external coordination.
Contains(HexCoord)
Determines whether the specified coordinate is addressable and populated in this grid.
Declaration
public bool Contains(HexCoord coord)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The coordinate to test. |
Returns
| Type | Description |
|---|---|
| bool |
For dense grids, returns
For sparse grids, returns |
Remarks
This method is equivalent to checking whether TryGet(TCoord, out TCell) would return
true for the same coordinate. Use it when you only need the existence check
and do not need the value.
See Also
CreateBuilder()
Creates a new fluent ScyllaHexGrid<TCell>.Builder for configuring and constructing a ScyllaHexGrid<TCell> instance with complex parameters.
Declaration
public static ScyllaHexGrid<TCell>.Builder CreateBuilder()
Returns
| Type | Description |
|---|---|
| ScyllaHexGrid<TCell>.Builder | A new ScyllaHexGrid<TCell>.Builder with default settings (1x1, layout unset). |
DrawLine(HexCoord, HexCoord, Span<HexCoord>)
Traces a straight line of hex cells from from to to
using linear interpolation in cube space and writes only the in-bounds cells into the buffer.
Both endpoints are included if they are in bounds.
Declaration
public int DrawLine(HexCoord from, HexCoord to, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | from | The starting axial coordinate (inclusive). |
| HexCoord | to | The ending axial coordinate (inclusive). |
| Span<HexCoord> | buffer | A span to receive the in-bounds hex coordinates along the line. Writing stops when the buffer is full. |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written to |
Remarks
The number of cells on the line equals HexCoord.Distance(from, to) + 1.
An epsilon nudge of 1e-6f is added to the starting Q and R values to break ties
consistently when the line passes exactly through a hex boundary edge or corner,
preventing ambiguous rounding results.
Only in-bounds cells are written; out-of-bounds intermediate cells are skipped.
Fill(TCell)
Fills all cells with the specified value.
Declaration
public void Fill(TCell value)
Parameters
| Type | Name | Description |
|---|---|---|
| TCell | value | The value to fill with. |
GetEnumerator()
Returns an enumerator that iterates through all cells.
Declaration
public ScyllaHexGrid<TCell>.Enumerator GetEnumerator()
Returns
| Type | Description |
|---|---|
| ScyllaHexGrid<TCell>.Enumerator | An enumerator for allocation-free iteration. |
GetNeighborsNonAlloc(HexCoord, Span<HexCoord>)
Writes the in-bounds neighbors of the specified coordinate into the provided buffer.
Declaration
public int GetNeighborsNonAlloc(HexCoord coord, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The coordinate to find neighbors for. |
| Span<HexCoord> | buffer | A span of at least 6 elements to receive neighbor coordinates. |
Returns
| Type | Description |
|---|---|
| int | The number of neighbors written (up to 6). |
GetRange(HexCoord, int, Span<HexCoord>)
Writes all in-bounds hexes within range steps of center
into the provided buffer, including the center itself.
A range of N includes up to 1 + 3 * N * (N + 1) hexes; the actual count may be
lower for cells near the grid boundary.
Declaration
public int GetRange(HexCoord center, int range, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | center | The center coordinate of the range query. |
| int | range | The maximum number of hex steps from |
| Span<HexCoord> | buffer | A span to receive the in-bounds hex coordinates. Writing stops when the buffer is full. |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written to |
GetRing(HexCoord, int, Span<HexCoord>)
Writes all in-bounds hexes at exactly radius hex steps from
center into the provided buffer.
A full ring at radius N contains exactly 6 * N hexes; radius = 0
yields only the center hex itself.
Declaration
public int GetRing(HexCoord center, int radius, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | center | The center coordinate of the ring. |
| int | radius | The ring radius in hex steps. Must be at least 0. A radius of 0 returns only the center hex (if in bounds). |
| Span<HexCoord> | buffer | A span to receive the in-bounds hex coordinates. Writing stops when the buffer is full. |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written to |
Remarks
The ring is traced starting at the hex offset W×radius from the center, then walking
clockwise around all six sides of the ring. The actual count returned may be fewer than
6 * N when part of the ring falls outside the grid bounds.
GridToWorld(HexCoord)
Converts a hex coordinate to world-space position using the grid's layout.
Declaration
public Vector2 GridToWorld(HexCoord coord)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The hex coordinate. |
Returns
| Type | Description |
|---|---|
| Vector2 | The world-space center of the hex. |
IsInBounds(HexCoord)
Determines whether the specified coordinate is within the grid bounds.
Declaration
public bool IsInBounds(HexCoord coord)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The hex coordinate. |
Returns
| Type | Description |
|---|---|
| bool | True if the coordinate is within bounds. |
TryGet(HexCoord, out TCell)
Attempts to retrieve the value stored at the specified coordinate without throwing on failure.
Declaration
public bool TryGet(HexCoord coord, out TCell value)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The grid coordinate to look up. |
| TCell | value | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|
Remarks
Prefer this method over direct indexer access when the coordinate's validity is not guaranteed, as it avoids the cost of exception handling on out-of-bounds access. For dense grids, "within bounds" means the coordinate maps to a valid flat-array index. For sparse grids, "within bounds" additionally requires that the cell has been set.
See Also
TrySet(HexCoord, TCell)
Attempts to store a value at the specified coordinate without throwing on failure.
Declaration
public bool TrySet(HexCoord coord, TCell value)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The grid coordinate to write to. |
| TCell | value | The value to store at |
Returns
| Type | Description |
|---|---|
| bool |
|
Remarks
For dense grids, this writes to the pre-allocated cell at
coord and returns false if the coordinate falls outside
the grid's dimensions.
For sparse grids, this inserts or updates the entry at
coord and returns false only when the grid is bounded
and coord falls outside the defined bounds. On unbounded sparse
grids this method always returns true.
A successful call increments CellCount on sparse grids when
coord is newly written for the first time.
See Also
WorldToGrid(Vector2)
Converts a world-space position to a hex coordinate using the grid's layout.
Declaration
public HexCoord WorldToGrid(Vector2 worldPos)
Parameters
| Type | Name | Description |
|---|---|---|
| Vector2 | worldPos | The world-space position. |
Returns
| Type | Description |
|---|---|
| HexCoord | The nearest hex coordinate. |