using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Assets.Scripts.Utils; using UnityEngine; namespace Assets.Scripts.MapGeneration { internal class DefaultCellDelegates { public static bool DefaultCanGrow(Cell cell) { return true; } public static bool DefaultWillGrow(Cell cell) { return true; } public static Cell DefaultPickTarget(Map map, Cell origin) { return CellularAutomaton.GetNeighbors(map, origin).FirstOrDefault(); } } public class CellularAutomaton { #region Delegates public delegate IEnumerable<Cell> Filter(Map map); public delegate bool CanGrow(Cell cell); public delegate bool WillGrow(Cell cell); public delegate Cell Picktarget(Map map, Cell origin); #endregion #region Fields private Map _map; private List<Cell> _toProcess; private CanGrow _canGrowRule; private WillGrow _willGrowRule; private Picktarget _pickTargetRule; private TileType _targetType; #endregion #region Ctors public CellularAutomaton(Map map, TileType targetType, int startX = 0, int startY = 0) { _map = map; _targetType = targetType; _canGrowRule = DefaultCellDelegates.DefaultCanGrow; _willGrowRule = DefaultCellDelegates.DefaultWillGrow; _pickTargetRule = DefaultCellDelegates.DefaultPickTarget; _toProcess = new List<Cell> {new Cell(startX, startY, targetType)}; } #endregion #region Methods public void Step() { var newCells = new List<Cell>(); foreach (var cell in _toProcess) { if (!_canGrowRule(cell) || !_willGrowRule(cell)) continue; Grow(_pickTargetRule(_map, cell), _targetType); newCells.Add(cell); } _toProcess = newCells; } public static IEnumerable<Cell> GetNeighbors(Map map, Cell origin) { var ret = new List<Cell>(); for (var x = origin.Position.x - 1; x <= origin.Position.x + 1; x++) { for (var y = origin.Position.y - 1; y <= origin.Position.y + 1; y++) { if ((Math.Abs(x - origin.Position.x) > .1f || Math.Abs(y - origin.Position.y) > .1f) && IsInMapRange(map, (int) x, (int) y) && map[(uint) x, (uint) y] != origin.Type) { ret.Add(new Cell((int) x, (int) y, map[(uint) x, (uint) y])); } } } return ret; } private void Grow(Cell targetCell, TileType targetType) { targetCell.Type = targetType; } private static bool IsInMapRange(Map map, int x, int y) { return (x >= 0 && x < map.Columns && y >= 0 && y < map.Rows); } #endregion } }