private Vector2?GetBestPosition(CellManagerData data)
        {
            Vector2?bestPosition  = null;
            double  biasBest      = -1;
            double  biasMate      = 40d;
            double  biasFoodPoint = 55d;

            for (int i = 0; i < 8; i++)
            {
                double biasCurrent   = 0;
                Tile   tileInspected = data.TilesSurrounding[i];
                if (tileInspected == null)
                {
                    continue;
                }
                Cell mate = GetMatingCell(data, i);
                if (mate != null &&
                    HasEnergy(data.CellCurrent, data.CellCurrent.EnergyNeededToReproduce).Item1&&
                    HasEnergy(mate, mate.EnergyNeededToReproduce).Item1)
                {
                    biasCurrent += biasMate;
                }
                double biasFoodCurrent = tileInspected.Food * biasFoodPoint;
                biasCurrent += biasFoodCurrent;
                if (biasCurrent > biasBest)
                {
                    biasBest     = biasCurrent;
                    bestPosition = tileInspected.Position;
                }
            }
            return(bestPosition);
        }
 public void Tick(CellManagerData data)
 {
     PhaseEliminative(data);
     PhaseMurrative(data);
     PhaseAnimative(data);
     PhaseDigestive(data);
     PhaseProductive(data);
 }
        private bool Mate(CellManagerData data)
        {
            Cell mate = GetMatingCell(data);

            if (mate != null)
            {
                return(MateInternal(data.CellCurrent, mate, data.Map));
            }
            return(false);
        }
 private Cell GetMatingCellSurrounding(CellManagerData data)
 {
     List <Cell>[] cellsTiles = data.CellsSurrounding;
     for (int i = 0; i < cellsTiles.Length; i++)
     {
         Cell cell = GetMatingCell(data, i);
         if (cell != null)
         {
             return(cell);
         }
     }
     return(null);
 }
        private Cell GetMatingCell(CellManagerData data, int index = 8)
        {
            List <Cell> cellsOnTile = data.CellsSurrounding[index];

            foreach (Cell cell in cellsOnTile)
            {
                if (HasEnergy(cell, cell.EnergyNeededToReproduce).Item1)
                {
                    return(cell);
                }
            }
            return(null);
        }
        private void CheckAndKill(CellManagerData data)
        {
            Cell   cell   = data.CellCurrent;
            double needed = cell.EnergyNeededToTick;

            if (!HasEnergy(cell, needed).Item1)
            {
                Kill(cell, data.Map, "Not enough energy to survive");
            }
            else
            {
                DrainEnergy(cell, needed);
            }
        }
        private void Move(CellManagerData data)
        {
            Cell cell = data.CellCurrent;

            if (!HasEnergy(cell, cell.EnergyNeededToMove).Item1)
            {
                return;
            }
            Vector2?newPosition = GetBestPosition(data);

            if (newPosition == null)
            {
                return;
            }

            Logger.Logger.Log(cell + " Moving from " + cell.Position + " to " + newPosition);

            DrainEnergy(cell, cell.EnergyNeededToMove);
            data.Map.MoveCell(cell, (Vector2)newPosition);
        }
        private void Eat(CellManagerData data)
        {
            Tile tile = data.TileCurrent;
            Cell cell = data.CellCurrent;

            double foodAvailable  = tile.Food;
            double foodCapacity   = cell.EnergyCapacity / cell.RatioFoodEnergy;
            double foodConsumable = foodCapacity - (cell.Energy / cell.RatioFoodEnergy);
            double foodToEat      = (foodConsumable >= foodAvailable) ? foodAvailable : foodConsumable;

            foodToEat = (foodToEat > cell.MaxFoodEatenOnTick) ? cell.MaxFoodEatenOnTick : foodToEat;

            Logger.Logger.Log(cell + " Eating " + foodToEat);
            Logger.Logger.Log(cell + " Tile_Before: " + tile.Food);
            tile.Food -= foodToEat;
            Logger.Logger.Log(cell + " Tile_After: " + tile.Food);

            Logger.Logger.Log(cell + " Cell_Before: " + cell.Energy);
            AddEnergy(cell, foodToEat * cell.RatioFoodEnergy);
            Logger.Logger.Log(cell + " Cell_After: " + cell.Energy);
        }
 private void PhaseMurrative(CellManagerData data)
 {
     Mate(data);
 }
 private void PhaseProductive(CellManagerData data)
 {
 }
 private void PhaseDigestive(CellManagerData data)
 {
     Eat(data);
 }
 private void PhaseAnimative(CellManagerData data)
 {
     Move(data);
 }
 private void PhaseEliminative(CellManagerData data)
 {
     CheckAndKill(data);
 }