using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using Life.Misc; namespace Life.Automaton { [Serializable] public abstract class BasicField : IField, IDeserializationCallback { [NonSerialized] List> _observers = new List>(); protected BasicField(int width, int height) { Size = new Size(width, height); _cells = new Cell[width, height]; for (int x = 0; x < width; x++) for (int y = 0; y < height; y++) _cells[x, y] = new Cell(); } private Cell[,] _cells; public Size Size { get; private set; } public Cell this[int x, int y] { get => _cells[x, y]; private set { _cells[x, y] = value; _observers.ForEach(observer => observer.OnNext(this)); } } public IEnumerable Cells => _cells.Cast(); public abstract IEnumerable Neighbours(int x, int y); public void Transform(IRule rule) { _cells = rule.Next(this); Notify(); } public void Notify() { _observers.ForEach(observer => observer.OnNext(this)); } public void Resize(int width, int height) { var cells = new Cell[width, height]; for (int x = 0; x < width; x++) for (int y = 0; y < height; y++) cells[x, y] = (x >= Size.Width || y >= Size.Height) ? new Cell() : _cells[x, y]; Size = new Size(width, height); _cells = cells; Notify(); } public IDisposable Subscribe(IObserver observer) { _observers.Add(observer); return new DelegateUnsubscriber(() => _observers.Remove(observer)); } public void OnDeserialization(object sender) { _observers = new List>(); } } }