private static double GetScoreForBuilding(GameState state, BlueprintResidenceBuilding building)
        {
            double ret = 0;

            if (state.MinTemp < 0)
            {
                ret += 10 / building.Emissivity;
            }
            if (state.HousingQueue - 5 < building.MaxPop)
            {
                ret += 100;
            }
            else
            {
                ret -= 70;
            }
            if (state.Funds - building.Cost - building.MaintenanceCost * 2 < 10000)
            {
                ret += building.IncomePerPop * 10;
                ret -= 60;
            }
            if (state.Funds > 20000)
            {
                ret -= building.BaseEnergyNeed * 3;
                ret += building.Co2Cost / 3;
                ret += building.MaxHappiness * 30;
            }
            ret += 100 - building.Co2Cost / 5.0;
            ret -= building.BaseEnergyNeed * 5;
            ret += !state.ResidenceBuildings.Any(t => t.BuildingName == building.BuildingName) ? 50 : 0;

            return(ret);
        }
        internal static Bundle GetBestResidenceBundle(BlueprintResidenceBuilding building, GameLayer layer)
        {
            var state     = layer.GetState();
            int turnsLeft = (state.MaxTurns - state.Turn - (int)Math.Ceiling(100.0 / building.BuildSpeed) - 1);
            var pos       = GetBestResidencePosition(layer);

            if (pos == null)
            {
                return(null);
            }
            double potentialScore = (building.MaxHappiness + Constants.AVG_EFFECT_HAPPINESS_INCREASE) * building.MaxPop * turnsLeft * Constants.AVG_POP_HAPPINESS_PRECENT / 10;

            if (!state.ResidenceBuildings.Any(t => t.BuildingName == building.BuildingName))
            {
                potentialScore += turnsLeft * Constants.TARGET_END_POP_COUNT * Constants.AVG_POP_HAPPINESS * Constants.AVG_POP_HAPPINESS_PRECENT * 0.1 / 30;
            }
            //FIXA DET UNDER DENNA
            double avgTemp     = Math.Max(state.MinTemp, state.MinTemp + (state.MaxTemp - state.MinTemp) / 2 - 4);
            double avgEnergyIn = Math.Max(building.BaseEnergyNeed, ((21 - avgTemp) * building.Emissivity - Constants.DEGREES_PER_POP * building.MaxPop) / Constants.DEGREES_PER_EXCESS_MWH + building.BaseEnergyNeed);

            if (state.UtilityBuildings.Any(t => t.BuildingName == "WindTurbine" && Math.Abs(pos.x - t.Position.x) + Math.Abs(pos.y - t.Position.y) <= 2))
            {
                avgEnergyIn = Math.Max(0, avgEnergyIn - 3.4);
            }
            if (state.Funds > 50000)
            {
                avgEnergyIn = Math.Max(0, avgEnergyIn - 3.4);
            }

            var el      = Helper.GetEnergyLevel(layer, Helper.GetEnergyConsumation(layer));
            var elAfter = Helper.GetEnergyLevel(layer, Helper.GetEnergyConsumation(layer) + avgEnergyIn);

            if (el.CostPerMwh != elAfter.CostPerMwh)
            {
                potentialScore -= (Helper.GetEnergyConsumation(layer) + avgEnergyIn) * elAfter.TonCo2PerMwh * turnsLeft + (Helper.GetEnergyConsumation(layer)) * el.TonCo2PerMwh * turnsLeft;
            }
            else
            {
                potentialScore -= avgEnergyIn * elAfter.TonCo2PerMwh * turnsLeft;
            }

            potentialScore += 15 * building.MaxPop;
            potentialScore -= building.MaxPop * Constants.CO2_PER_POP * turnsLeft;
            potentialScore -= building.Co2Cost;

            Bundle bundle = new Bundle
            {
                TotalIncome    = building.IncomePerPop * building.MaxPop * turnsLeft,
                ExtraCost      = building.MaintenanceCost * turnsLeft / Math.Ceiling(55.0 / (building.DecayRate + Constants.AVG_DECAY_INCREASE)) + elAfter.CostPerMwh * avgEnergyIn * turnsLeft,
                UpfrontCost    = building.Cost,
                PotentialScore = potentialScore,
                Turn           = new PlaceBuildingTurn(pos.x, pos.y, building, state.GameId),
                EnergyNeed     = avgEnergyIn
            };

            return(bundle);
        }
        public static Turn GetBestPlacedBuilding(GameLayer gameLayer)
        {
            Turn placeBuildingTurn = null;
            var  state             = gameLayer.GetState();

            if ((state.Funds < 5000 && state.ResidenceBuildings.Count > 0) || state.Turn > 650)
            {
                return(null);
            }
            int spaceLeft = 0;

            foreach (var building in state.ResidenceBuildings)
            {
                spaceLeft += state.AvailableResidenceBuildings.First(x => x.BuildingName == building.BuildingName).MaxPop - building.CurrentPop;
            }
            if (state.Turn > 650 || spaceLeft > 0)
            {
                return(null);
            }
            if (gameLayer.GetState().Funds < 5000 && gameLayer.GetState().ResidenceBuildings.Count > 0)
            {
                return(null);
            }
            if (state.QueueHappiness > Constants.QUEUE_MAX_HAPPINESS - 5 || state.HousingQueue > Constants.LONG_QUEUE - 1)
            {
                double score = 0;
                BlueprintResidenceBuilding toBuild = null;
                foreach (var building in state.AvailableResidenceBuildings)
                {
                    if (building.ReleaseTick > state.Turn)
                    {
                        continue;
                    }
                    double s = GetScoreForBuilding(state, building);
                    if (score < s && (building.Cost + 5000 <= state.Funds || (building.Cost <= state.Funds && state.ResidenceBuildings.Count == 0)))
                    {
                        toBuild = building;
                        score   = s;
                    }
                }
                if (toBuild == null)
                {
                    return(null);
                }
                var pos = GetBestPos(state);
                return(new PlaceBuildingTurn(pos.x, pos.y, toBuild, state.GameId));
            }
            return(placeBuildingTurn);
        }