/// <summary>
 /// Serialize a CA, writing it to a configuration file in XML format
 /// </summary>
 /// <param name="filename">The name of the file to read from</param>
 /// <param name="ca">The CA to serialize</param>
 public static void Serialize(string filename, CA ca)
 {
     XmlSerializer serializer = new XmlSerializer(typeof(CA));
     XmlTextWriter writer = new XmlTextWriter(filename, new UnicodeEncoding());
     writer.Formatting = Formatting.Indented;
     serializer.Serialize(writer, ca);
     writer.Flush();
     writer.Close();
 }
        public CALoaderWindow(CA currentCA)
        {
            neighborhood = new ObservableCollection<OPoint>();
            neighborhood.Add(new OPoint(0, 0));
            ca = currentCA;
            InitializeComponent();

            // Load values of curernt CA into fields, if available
            if (ca != null) populateFields();
        }
        private ConcurrentQueue<Cell[]> updated; // Cells updated since last checked by client

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initialize a new simulation with a blank grid (with all cells in the default state) of the default size.
        /// </summary>
        public Simulation()
        {
            toCheck = new SortedSet<CPoint>(new PointComparer());
            toUpdate = new ConcurrentQueue<Cell>();
            updated = new ConcurrentQueue<Cell[]>();
            grid = new uint[1][];
            ca = new CA();
            initGridBlank(defaultX, defaultY);
            refresh = defaultRefresh;
            throttled = false;
        }
        /// <summary>
        /// Attempt to compile delta function code entered. Any compiler
        /// messages are displayed.
        /// </summary>
        private void compile(object sender, RoutedEventArgs e)
        {
            // Gather information entered
            string deltaStr = deltaInputBox.Text;
            int numStates = (numStatesInputBox.Text == "") ? 1 : int.Parse(numStatesInputBox.Text);
            uint defaultState = (defaultStateInputBox.Text == "") ? 0 : uint.Parse(defaultStateInputBox.Text);
            CPoint[] neighbors = new CPoint[Neighborhood.Count];
            int i = 0;
            foreach (OPoint p in Neighborhood) {
                neighbors[i] = new CPoint(p.X, p.Y);
                i++;
            }

            // Attempt to compile a new CA with the entered information
            ca = new CA(numStates, defaultState, neighbors, deltaStr);
            compileMesseageOutputBox.Text = ca.compileDelta();
        }
        /// <summary>
        /// Open an open file dialog to let the user choose a CA configuration
        /// file, and attempt to load a CA from it.
        /// </summary>
        private void loadFromFile(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openCADialog = new OpenFileDialog();
            openCADialog.Filter = "Cellular Automata File (.xml)|*.xml|All Files|*.*";

            // Open selected file and parse results
            if (openCADialog.ShowDialog() == true) {
                filenameBox.Text = openCADialog.FileName;
                ca = CASerializer.Deserialize(openCADialog.FileName);

                // If the file was valid, put results back into input fields
                if (ca != null) populateFields();

                // Otherwise, ignore it and display an error message
                else MessageBox.Show("Error: invalid cellular automata file", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }
        /// <summary>
        /// Load the specified CA into this simulation, and clear the grid if necessary
        /// </summary>
        /// <param name="newCA">A CA representing a CA and its parameters</param>
        /// <returns>True if the CA is valid, or false otherwise</returns>
        public bool initCA(CA newCA)
        {
            // If an incompatible CA has previously been run, clear the grid
            if (getNumStates() > newCA.NumStates) initGridBlank(gridSizeX, gridSizeY);

            // Load and compile the new CA
            string result;
            lock (ca) {
                ca = newCA;
                result = newCA.compileDelta();
                if (ca.Neighborhood != null) optimizing = true;
                else optimizing = false;
            }

            // Return true if the CA's delta function compiled successfully
            return (result == "Delta function successfully compiled");
        }
        /// <summary>
        /// Open a window to load CA parapeters and, if successful, use it in
        /// the current simulation
        /// </summary>
        private void loadCA(object sender, RoutedEventArgs e)
        {
            // Open CA loader window
            CALoaderWindow caLoaderWindow = new CALoaderWindow(ca);
            caLoaderWindow.Owner = this;
            caLoaderWindow.ShowDialog();

            // If a CA was successfully compiled, use it in the current simulation
            if (caLoaderWindow.CompiledCA != null) {
                // Send the uncompiled CA and let the server recompile (can't serialize an assembly)
                ca = caLoaderWindow.CompiledCA.copyCA();
                simClient.initCA(ca);

                // If not enough colors are defined for the new CA, generate more
                if (simClient.getNumStates() > colorList.Length) getDefaultColors(simClient.getNumStates());

                // Update default state (will not be immediately applied to grid unless it needs to be cleared)
                defaultState = ca.DefaultState;

                // If an incompatible CA has previously been run, clear the grid
                bool clearedGrid = false;
                if (clearedGrid = (simClient.getNumStates() > caLoaderWindow.CompiledCA.NumStates))
                    initDisplay(gridSizeX, gridSizeY);

                // Update controls
                enableMenuItems();
                generation = 0;
                generationTextBlock.Text = "Generation: 0";
                statusTextBlock.Text = "New cellular automata loaded";
                if (clearedGrid) statusTextBlock.Text += " (grid cleared)";
            }
        }