using System; using System.Collections.Generic; using UnityEngine; namespace BlockOutReplica.Domain { public enum DoorSide { Top, Bottom, Left, Right } [Serializable] public struct GridPosition : IEquatable { public int X; public int Y; public GridPosition(int x, int y) { X = x; Y = y; } public bool Equals(GridPosition other) => X == other.X && Y == other.Y; public override bool Equals(object obj) => obj is GridPosition other && Equals(other); public override int GetHashCode() => (X * 397) ^ Y; } public sealed class PieceDefinition { public int ColorId { get; } public IReadOnlyList Cells { get; } public int InitialIceCount { get; } public bool HasLayer { get; } public int LayerColorId { get; } public PieceDefinition(int colorId, IReadOnlyList cells, int initialIceCount = 0, bool hasLayer = false, int layerColorId = 0) { ColorId = colorId; Cells = cells; InitialIceCount = Math.Max(0, initialIceCount); HasLayer = hasLayer; LayerColorId = layerColorId; } } public sealed class DoorDefinition { public int ColorId { get; } public IReadOnlyList Cells { get; } public DoorSide Side { get; } public int InitialIceCount { get; } public DoorDefinition(int colorId, IReadOnlyList cells, DoorSide side, int initialIceCount = 0) { ColorId = colorId; Cells = cells; Side = side; InitialIceCount = Math.Max(0, initialIceCount); } } public sealed class CurtainLockDefinition { public IReadOnlyList Cells { get; } public int InitialLockCount { get; } public CurtainLockDefinition(IReadOnlyList cells, int initialLockCount) { Cells = cells; InitialLockCount = Math.Max(0, initialLockCount); } } public sealed class LevelDefinition { public IReadOnlyList Pieces { get; } public IReadOnlyList Doors { get; } public IReadOnlyList Walls { get; } public IReadOnlyList Cells { get; } public IReadOnlyList CurtainLocks { get; } public GridPosition BoardStart { get; } public int MinX { get; } public int MaxX { get; } public int MinY { get; } public int MaxY { get; } public Vector2 GridCenter => new Vector2((MinX + MaxX) * 0.5f, (MinY + MaxY) * 0.5f); public LevelDefinition(IReadOnlyList pieces, IReadOnlyList doors, IReadOnlyList walls, IReadOnlyList cells, GridPosition boardStart, int minX, int maxX, int minY, int maxY, IReadOnlyList curtainLocks = null) { Pieces = pieces; Doors = doors; Walls = walls; Cells = cells; BoardStart = boardStart; MinX = minX; MaxX = maxX; MinY = minY; MaxY = maxY; CurtainLocks = curtainLocks ?? Array.Empty(); } public Vector3 GridToWorld(GridPosition position, float height = 0f) { Vector2 center = GridCenter; return new Vector3(position.X - center.x, height, position.Y - center.y); } public Vector3 AverageWorld(IReadOnlyList positions, float height = 0f) { Vector3 result = Vector3.zero; for (int i = 0; i < positions.Count; i++) result += GridToWorld(positions[i], height); return positions.Count == 0 ? new Vector3(0f, height, 0f) : result / positions.Count; } } }