using System; namespace IslaApocalypse.Core { /// /// The world as a 2D GRID OF COLUMNS — one per horizontal cell. /// → `Design - Data - Column Model.md`, D-053. /// /// The grid is square and its side is a GENERATION PARAMETER, never a constant. It is carried /// as a so that every derived distance in the project is forced /// through the one scaling rule. → `Design - Tooling - Scaling Discipline.md`. /// /// ⚠ SHAPE ONLY, PHASE 0. Chunking for streaming, region files, serialization and the mesher /// interface are all later phases. A flat array is the honest Phase 0 representation: it says /// "grid of columns" and commits to nothing about how it will be paged. /// /// ⚠ NOTHING ABOUT WATER LIVES HERE. Water is an overlay over the grid, not a layer in it. /// public sealed class ColumnGrid { private readonly Column[] _columns; /// The scale this world was generated at. Side length, scale factor, derived distances. public GenerationScale Scale { get; } /// Grid side in columns. 1 column = 1 metre (D-002, 1:1 scale). public int Side => Scale.MapSize; public ColumnGrid(GenerationScale scale) { Scale = scale; _columns = new Column[(long)scale.MapSize * scale.MapSize <= int.MaxValue ? scale.MapSize * scale.MapSize : throw new ArgumentOutOfRangeException(nameof(scale), scale.MapSize, "MapSize squared exceeds a single flat array. Chunked storage is a later phase — see the class comment.")]; } /// The column at (x, y). Null until one is placed — Phase 0 allocates no columns. public Column this[int x, int y] { get => _columns[Index(x, y)]; set => _columns[Index(x, y)] = value; } private int Index(int x, int y) { if ((uint)x >= (uint)Side) throw new ArgumentOutOfRangeException(nameof(x), x, $"x outside [0,{Side})."); if ((uint)y >= (uint)Side) throw new ArgumentOutOfRangeException(nameof(y), y, $"y outside [0,{Side})."); return y * Side + x; } public override string ToString() => $"ColumnGrid({Side}x{Side})"; } }