private MainViewModel BuildMainDataContext()
        {
            var width = Properties.Settings.Default.EcosystemWidth;
            var height = Properties.Settings.Default.EcosystemHeight;

            // the event aggregator might be used by view models to inform of changes
            var eventaggregator = new EventAggregator();

            var habitats = new Habitat[width, height];
            var habitatViewModels = new List<List<HabitatViewModel>>();

            for (var x = 0; x < width; x++)
            {
                habitatViewModels.Add(new List<HabitatViewModel>());

                for (var y = 0; y < height; y++)
                {
                    // initially set each habitat to have an unknown environment and no organism
                    var environment = new Environment(Terrain.Unknown, false);
                    var environmentViewModel = new EnvironmentViewModel(environment, eventaggregator);

                    var organismViewModel = new OrganismViewModel(null, eventaggregator);

                    var habitat = new Habitat(environment, null);
                    var habitatViewModel = new HabitatViewModel(habitat, environmentViewModel, organismViewModel, eventaggregator);

                    habitats[x, y] = habitat;
                    habitatViewModels[x].Add(habitatViewModel);
                }
            }

            var ecosystem = new Ecosystem(habitats, new Dictionary<Organism, Habitat>());
            var ecosystemViewModel = new EcosystemViewModel(ecosystem, habitatViewModels, eventaggregator);

            this.InitialiseTerrain(ecosystem);
            var initialOrganismCoordinates = this.InitialiseOrganisms(ecosystem);

            // TODO: do this in InitialiseOrganisms
            // boshed together so the organisms are visible before ecosystem is switched on the first time
            foreach (var organismCoordinate in initialOrganismCoordinates)
            {
                habitatViewModels[organismCoordinate.X][organismCoordinate.Y].RefreshOrganismViewModel();
            }

            // TODO: setting up the summary view after organisms initialised... how to handle this nicely
            var organismViewModels = habitatViewModels.SelectMany(habitatViewModel => habitatViewModel)
                                                      .Select(habitatViewModel => habitatViewModel.OrganismViewModel)
                                                      .Where(organismViewModel => organismViewModel.HasOrganism).ToList();
            var organismSummaryViewModel = new OrganismSummaryViewModel(ecosystem, organismViewModels, eventaggregator);

            var main = new Main(ecosystem);
            var mainViewModel = new MainViewModel(main, ecosystemViewModel, organismSummaryViewModel, eventaggregator);

            return mainViewModel;
        }
        public Ecosystem(Habitat[,] habitats, Dictionary<Organism, Habitat> organismHabitats)
        {
            this.Habitats = habitats;
            this.OrganismHabitats = organismHabitats;

            this.HealthBias = 1;

            this.HabitatCoordinates = new Dictionary<Habitat, Coordinates>();
            for (var i = 0; i < this.Width; i++)
            {
                for (var j = 0; j < this.Height; j++)
                {
                    this.HabitatCoordinates.Add(this.Habitats[i, j], new Coordinates(i, j));
                }
            }

            this.PheromoneDepositPerTurn = 0.01;
            this.PheromoneFadePerTurn = 0.001;
        }
        private static Habitat[,] GenerateBaseHabitats(int width, int height)
        {
            var habitats = new Habitat[width,height];
            for (var x = 0; x < width; x++)
            {
                for (var y = 0; y < height; y++)
                {
                    var environment = new Environment(Terrain.Unknown, false);
                    habitats[x, y] = new Habitat(environment, null);
                }
            }

            return habitats;
        }
 public MockEcosystem(Habitat[,] habitats, Dictionary<Organism, Habitat> organismHabitats, Dictionary<Organism, Habitat> overriddenChosenHabitats)
     : base(habitats, organismHabitats)
 {
     this.OverriddenChosenHabitats = overriddenChosenHabitats;
 }
        private void MoveOrganism(Organism organism, Habitat destination)
        {
            var source = this.OrganismHabitats[organism];

            // the organism cannot move if it is dead
            if (!organism.IsAlive)
            {
                throw new InvalidOperationException(
                    string.Format("Cannot move organism {0} to {1} because it is dead",
                                   organism, destination));
            }

            // the organism can only move to the destination if it is not obstructed
            if (destination.IsObstructed())
            {
                throw new InvalidOperationException(
                    string.Format("Cannot move organism {0} to {1} because the destination is obstructed",
                                  organism, destination));
            }

            // the organism can only move to the destination if it does not already contain an organism
            if (destination.ContainsOrganism())
            {
                throw new InvalidOperationException(
                    string.Format("Cannot move organism {0} to {1} because the destination is occupied by {2}",
                                  organism, destination, destination.Organism));
            }

            source.RemoveOrganism();
            destination.AddOrganism(organism);
            this.OrganismHabitats[organism] = destination;
        }
        private List<Habitat> GetNeighbouringHabitats(Habitat habitat)
        {
            var neighbouringHabitats = new List<Habitat>();

            var location = this.HabitatCoordinates[habitat];
            for (var x = location.X - 1; x <= location.X + 1; x++)
            {
                // do not carry on if x is out-of-bounds
                if (x < 0 || x >= this.Width)
                {
                    continue;
                }

                for (var y = location.Y - 1; y <= location.Y + 1; y++)
                {
                    // do not carry on if y is out-of-bounds
                    if (y < 0 || y >= this.Height)
                    {
                        continue;
                    }

                    neighbouringHabitats.Add(this.Habitats[x, y]);
                }
            }

            return neighbouringHabitats;
        }