private Board CreateBoard(Settings settings)
        {
            var board = new Board
            {
                Size = new Location {
                    X = settings.Width, Y = settings.Height
                },
                Tiles  = new Tile[settings.Width, settings.Height],
                Pieces = new List <IPiece>(),
                //MaxAge = settings.MaxAge
            };

            int xpos = 0;
            int ypos = 0;

            for (int i = 0; i < settings.Width * settings.Height; i++)
            {
                var grass = new Grass
                {
                    Location = new Location {
                        X = xpos, Y = ypos
                    },
                    Energy = Rando.Next(50) //+ 50
                };

                board.Tiles[xpos, ypos] = new nimble_life.Tile
                {
                    Grass    = grass,
                    Location = new Location {
                        X = xpos, Y = ypos
                    }
                };

                if (Rando.Next(settings.OneInThisIsHerby) == 1)
                {
                    var herby = new Herbivore()
                    {
                        Location = new nimble_life.Location {
                            X = xpos, Y = ypos
                        },
                        Energy        = Rando.Next(75),
                        Species       = "Electric Sheep",
                        Color         = System.Drawing.Color.Black,
                        Age           = Rando.Next(30),
                        AgeOfMaturity = Settings.AgeOfMaturity,
                        Genes         = new Dictionary <string, float>()
                    };
                    herby.Genes = Clone(greatestGenes);
                    board.Pieces.Add(herby);
                    board.Tiles[xpos, ypos].Animal = herby;
                }
                else if (Rando.Next(settings.OneInThisIsRobot) == 1)
                {
                    var robby = new Robot()
                    {
                        Location = new nimble_life.Location {
                            X = xpos, Y = ypos
                        },
                        Energy        = Rando.Next(75),
                        Species       = "Robot",
                        Color         = System.Drawing.Color.Black,
                        Age           = Rando.Next(30),
                        AgeOfMaturity = Settings.AgeOfMaturity,
                        Genes         = new Dictionary <string, float>()
                    };

                    robby.Genes = Clone(greatestGenes);
                    board.Pieces.Add(robby);
                    board.Tiles[xpos, ypos].Animal = robby;
                }

                xpos++;
                if (xpos >= settings.Width)
                {
                    xpos = 0;
                    ypos++;
                }
            }

            return(board);
        }
        public IPiece TakeTurn(Board board)
        {
            if (this.IsDead)
            {
                return(null);
            }

            IPiece result = null;

            var moveDone     = false;
            var currentTile  = board.Tiles[this.Location.X, this.Location.Y];
            var neighbors    = board.GetNeighbors(this.Location.X, this.Location.Y);
            var bestNeighbor = currentTile;

            foreach (var t in neighbors)
            {
                if (t.Animal == null && t.Grass.Energy > bestNeighbor.Grass.Energy)
                {
                    bestNeighbor = t;
                }
            }

            if (!moveDone && bestNeighbor != currentTile &&
                (bestNeighbor.Grass.Energy > this.Genes[hg.WorthMovingTo.ToString()]))
            {
                // Move to it!
                currentTile.Animal  = null;
                bestNeighbor.Animal = this;
                this.Location.X     = bestNeighbor.Location.X;
                this.Location.Y     = bestNeighbor.Location.Y;
                this.Energy        -= 5; //TAKES energy to move...
                currentTile         = board.Tiles[this.Location.X, this.Location.Y];
                moveDone            = true;
            }
            else
            {
                // Takes energy to stand still!
                this.Energy -= 1;
            }

            if (!moveDone && currentTile.Grass.Energy > 15 && this.Energy < 100)
            {
                // Chew some.
                currentTile.Grass.Energy -= 15;
                this.Energy += 10; // Note inefficiency
            }

            this.Energy = Math.Min(100, this.Energy);

            // Consider trying to mate...
            if (Rando.Next() < this.Genes[hg.MatingProbability.ToString()] &&
                this.Age >= this.AgeOfMaturity)
            {
                var hottestNeighbor = this as IAnimal;
                foreach (var t in neighbors)
                {
                    if (t.Animal != null &&
                        t.Animal.Species == this.Species && // picky
                        t.Animal.IsDead == false &&                // picky!
                        t.Animal.Age > t.Animal.AgeOfMaturity && // picky
                        t.Animal.Energy >= hottestNeighbor.Energy) //picky
                    {
                        hottestNeighbor = t.Animal;
                    }
                }

                if (hottestNeighbor != this) // picky
                {
                    if (hottestNeighbor.MatingOffers == null)
                    {
                        hottestNeighbor.MatingOffers = new List <IAnimal>();
                    }
                    // swipe right
                    hottestNeighbor.MatingOffers.Add(this);
                }
            }

            if (this.MatingOffers != null && this.Energy > this.Genes[hg.EnergyRequiredBeforeConsideringOffspring.ToString()])
            {
                var bestOffer = this.MatingOffers
                                .Where(p =>
                                       p.IsDead == false &&
                                       p.Species == this.Species &&
                                       p.Age > p.AgeOfMaturity)
                                .OrderByDescending(p => p.Energy).FirstOrDefault();

                if (bestOffer != null)
                {
                    // Find an empty neighboring square to plonk a baby on...
                    bestNeighbor = null;

                    foreach (var t in neighbors)
                    {
                        if (t.Animal == null &&
                            (bestNeighbor == null || t.Grass.Energy > bestNeighbor.Grass.Energy) &&
                            t.Grass.Energy > this.Genes[hg.MinFoodAvailableForBaby.ToString()])    // what kind of a world are we bringing this child into...
                        {
                            bestNeighbor = t;
                        }
                    }

                    if (bestNeighbor != null)
                    {
                        var baby = new Herbivore
                        {
                            Species       = this.Species,
                            Energy        = (int)(this.Energy * this.Genes[hg.EnergyToBaby.ToString()]),
                            Age           = 0,
                            AgeOfMaturity = this.AgeOfMaturity,
                            Genes         = new Dictionary <string, float>()
                        };


                        var MaxMutationFactor = this.Genes[hg.MaxMutationFactor.ToString()];

                        foreach (var d in this.Genes.Keys)
                        {
                            var mutationFactor = (float)1 + (float)((Rando.Next() * MaxMutationFactor) - (MaxMutationFactor / 2));

                            // Cross over and mutation
                            baby.Genes[d] = Rando.Either(bestOffer.Genes[d], this.Genes[d]) * mutationFactor;
                        }

                        // Having babies really takes something out of you.
                        this.Energy -= baby.Energy;

                        baby.Location = new Location()
                        {
                            X = bestNeighbor.Location.X,
                            Y = bestNeighbor.Location.Y
                        };
                        bestNeighbor.Animal = baby;
                        result = baby;

                        // Get rid of all mating offers.
                        this.MatingOffers = null;
                    }
                    else
                    {
                        Debug.WriteLine("No empty tile found.");
                    }
                }
            }

            // shade of gray depends on energy levels
            var gray = Math.Max(0, Math.Min((int)(Energy * (256.0 / 100.0)), 255));

            this.Color = Color.FromArgb(gray, gray, gray);
            return(result);
        }