private void AutoSelectPolicy()
        {
            List<PolicyType> possibleTypes = Provider.Instance.PolicyTypes.Values.ToList();
            List<Policy> policies = new List<Policy>();
            IEnumerable<string> pastEraNames = Eras.Select(b => b.Name);

            // remove all policy types which will become active in future eras only
            possibleTypes.RemoveAll(a => !pastEraNames.Contains(a.EraName));

            PropabilityMap<PolicyType> typeMap = new PropabilityMap<PolicyType>();

            foreach (PolicyType type in possibleTypes)
            {
                // add only to evaluation if not already adopted
                if (!_policyTypes.Contains(type))
                    typeMap.AddItem(type, 1f / Flavours.Distance(type.Flavours, Flavours));
                else
                    policies.AddRange(type.Policies);
            }

            policies.RemoveAll(a => _policies.Contains(a));

            PropabilityMap<Policy> policyMap = new PropabilityMap<Policy>();

            foreach (Policy p in policies)
                policyMap.AddItem(p, 1f / Flavours.Distance(p.Flavours, Flavours));

            if (typeMap.Items.Count > 0)
            {
                PolicyType bestPolicyType = typeMap.Best;

                if (policyMap.Items.Count == 0)
                {
                    if (!AdoptPolicyType(bestPolicyType))
                        throw new Exception("There was an error while adopting " + bestPolicyType);
                }
                else
                {
                    Policy bestPolicy = policyMap.RandomOfBest3;
                    if (Flavours.Distance(bestPolicyType.Flavours, Flavours) < Flavours.Distance(bestPolicy.Flavours, Flavours))
                    {
                        if (!AdoptPolicyType(bestPolicyType))
                            throw new Exception("There was an error while adopting " + bestPolicyType);
                    }
                    else
                    {
                        if (!AdoptPolicy(bestPolicy))
                            throw new Exception("There was an error while adopting " + bestPolicy);
                    }
                }
            }
            else
            {
                if (policyMap.Items.Count == 0 )
                    throw new Exception("There must be at least one policy to select!");

                AdoptPolicy(policyMap.RandomOfBest3);
            }
        }
        public void DetermineGrandStragegy()
        {
            PropabilityMap<GrandStrategyData> map = new PropabilityMap<GrandStrategyData>();

            #region conquest strategy
            GrandStrategyData conquestStrategy = Provider.GetGrandStrategy("Conquest");

            if (conquestStrategy != null)
            {
                float conquestWeight = _diplomaticStatuses.Count == 0 && IsFirstRun ? AI_GRAND_STRATEGY_CONQUEST_NOBODY_MET_FIRST_TURN : 0;
                conquestWeight += _diplomaticStatuses.Count == 0 && !IsFirstRun ? AI_GRAND_STRATEGY_CONQUEST_NOBODY_MET_WEIGHT : 0;
                conquestWeight += _diplomaticStatuses.Exists(a => a.Status == BilateralStatus.AtWar) ? AI_GRAND_STRATEGY_CONQUEST_AT_WAR_WEIGHT : 0;

                conquestWeight += IsFirstRun ? AI_GRAND_STRATEGY_CONQUEST_MILITARY_STRENGTH_FIRST_TURN : 0;
                conquestWeight += AI_GRAND_STRATEGY_CONQUEST_POWER_RATIO_MULTIPLIER * MilitaryPowerValue;
                conquestWeight += AI_GRAND_STRATEGY_CONQUEST_CRAMPED_WEIGHT * CrampedValue;

                foreach (DiplomaticStatus status in _diplomaticStatuses)
                {
                    conquestWeight += status.HasBeenAttacked && !status.IsMinor ? AI_GRAND_STRATEGY_CONQUEST_WEIGHT_PER_MAJOR_ATTACKED : 0;
                    conquestWeight += status.HasBeenConquered && !status.IsMinor ? AI_GRAND_STRATEGY_CONQUEST_WEIGHT_PER_MAJOR_CONQUERED : 0;
                    conquestWeight += status.HasBeenAttacked && status.IsMinor ? AI_GRAND_STRATEGY_CONQUEST_WEIGHT_PER_MINOR_ATTACKED : 0;
                    conquestWeight += status.HasBeenConquered && status.IsMinor ? AI_GRAND_STRATEGY_CONQUEST_WEIGHT_PER_MINOR_ATTACKED : 0;
                }

                if( _grandStrategy == conquestStrategy )
                    conquestWeight += AI_GRAND_STRATEGY_CURRENT_STRATEGY_WEIGHT;

                if( !( _everHadStrategy.ContainsKey( conquestStrategy ) && _everHadStrategy[conquestStrategy] ) )
                    conquestWeight += AI_GRAND_STRATEGY_GUESS_NO_CLUE_WEIGHT;

                map.AddItem(conquestStrategy, conquestWeight);
            }
            #endregion conquest strategy

            #region culture strategy
            GrandStrategyData cultureStrategy = Provider.GetGrandStrategy("Culture");

            if (cultureStrategy != null)
            {
                float cultureWeight = CultureRatio * AI_GRAND_STRATEGY_CULTURE_RATIO_MULTIPLIER;

                if (IsEarly)
                {
                    cultureWeight /= AI_GRAND_STRATEGY_CULTURE_RATIO_EARLY_DIVISOR;

                    if (cultureWeight < AI_GRAND_STRATEGY_CULTURE_RATIO_EARLY_TURN_THRESHOLD)
                        cultureWeight = 0f;
                }

                if (_cities.Count > AI_GRAND_STRATEGY_CULTURE_MAX_CITIES)
                    cultureWeight = 0f;

                if( _grandStrategy == cultureStrategy )
                    cultureWeight += AI_GRAND_STRATEGY_CURRENT_STRATEGY_WEIGHT;

                if( !( _everHadStrategy.ContainsKey( cultureStrategy ) && _everHadStrategy[cultureStrategy] ) )
                    cultureWeight += AI_GRAND_STRATEGY_GUESS_NO_CLUE_WEIGHT;

                map.AddItem(cultureStrategy, cultureWeight);
            }
            #endregion culture strategy

            #region spaceship strategy
            GrandStrategyData spaceshipStrategy = Provider.GetGrandStrategy("Spaceship");

            if (spaceshipStrategy != null)
            {
                float spaceshipWeight = Wonders.FirstOrDefault( a => a.Name == "ApolloProgram" ) != null ? AI_GRAND_STRATEGY_SS_HAS_APOLLO_PROGRAM : 0;
                spaceshipWeight += AI_GRAND_STRATEGY_SS_TECH_PROGRESS_MOD * SpaceshipTechProgress;

                if( _grandStrategy == spaceshipStrategy )
                    spaceshipWeight += AI_GRAND_STRATEGY_CURRENT_STRATEGY_WEIGHT;

                if( !( _everHadStrategy.ContainsKey( spaceshipStrategy ) && _everHadStrategy[spaceshipStrategy] ) )
                    spaceshipWeight += AI_GRAND_STRATEGY_GUESS_NO_CLUE_WEIGHT;

                map.AddItem(spaceshipStrategy, spaceshipWeight);
            }
            #endregion spaceship strategy

            #region unitednations strategy
            GrandStrategyData unitednationsStrategy = Provider.GetGrandStrategy("UnitedNations");

            if (unitednationsStrategy != null)
            {
                float unitednationsWeight = 0f;

                foreach (DiplomaticStatus status in _diplomaticStatuses)
                {
                    unitednationsWeight += status.IsMinor && status.HasBeenAttacked ? AI_GRAND_STRATEGY_UN_EACH_MINOR_ATTACKED_WEIGHT : 0;
                    unitednationsWeight += status.Status == BilateralStatus.VoteForUN ? AI_GRAND_STRATEGY_UN_SECURED_VOTE_MOD : 0;
                }

                if( _grandStrategy == unitednationsStrategy )
                    unitednationsWeight += AI_GRAND_STRATEGY_CURRENT_STRATEGY_WEIGHT;

                if( !( _everHadStrategy.ContainsKey( unitednationsStrategy ) && _everHadStrategy[unitednationsStrategy] ) )
                    unitednationsWeight += AI_GRAND_STRATEGY_GUESS_NO_CLUE_WEIGHT;

                map.AddItem(unitednationsStrategy, unitednationsWeight);
            }
            #endregion unitednations strategy

            GrandStrategyData newStrategy = map.Random;

            if (newStrategy != _grandStrategy)
            {
                // grand stragety is set on first run or by 40% chance
                if( _grandStrategy == null || rand.Next(100) < 40)
                    ChangeGrandStrategy(newStrategy);
            }
        }
        public void SelectTarget()
        {
            switch (_unitAI)
            {
                case Types.UnitAI.Work:
                    PropabilityMap<WayPoints> propsWork = new PropabilityMap<WayPoints>();

                    foreach (HexPoint pt in Point.Neighbors)
                    {
                        if (Map[pt].CanEnter(this))
                            propsWork.AddItem(WayPoints.FromPath(Map.FindPath(this, pt)), _player.ImprovementLocationMap[pt] * (_player.ImprovementLocationMap.IsLocalMaximum(pt) ? 1.0f : 0.2f));
                    }

                    _path = propsWork.Random;
                    break;
                case Types.UnitAI.Settle:
                    PropabilityMap<WayPoints> propsSettle = new PropabilityMap<WayPoints>();

                    List<HexPoint> interest = GetTilesOfInterest(_settlerInterest);
                    foreach (HexPoint pt in interest)
                    {
                        Path path = Map.FindPath(this, pt);
                        if (path != null && path.IsValid)
                        {
                            propsSettle.AddItem(WayPoints.FromPath( path ), _player.CityLocationMap[pt] * (_player.CityLocationMap.IsLocalMaximum(pt) ? 1.0f : 0.2f));
                        }
                    }

                    _path = propsSettle.Random;
                    break;
                case Types.UnitAI.Attack:
                case Types.UnitAI.Explore:
                    PropabilityMap<WayPoints> propsExplore = new PropabilityMap<WayPoints>();

                    foreach (HexPoint pt in Point.Neighbors)
                    {
                        if (Map[pt].CanEnter(this))
                            propsExplore.AddItem(WayPoints.FromPath(Map.FindPath(this, pt)), 1);
                    }

                    _path = propsExplore.Random;
                    break;
                default:
                    throw new Exception("SelectTarget not prepared " + _unitAI);
            }

            return;
        }
        private void MakeResources()
        {
            for (int x = 0; x < Width; x++)
            {
                for (int y = 0; y < Height; y++)
                {
                    List<Ressource> possibleResources = new List<Ressource>();

                    MapCell cell = this[x, y];

                    foreach (string resName in cell.Terrain.PossibleRessources)
                        possibleResources.Add(Provider.GetRessource(resName));

                    foreach (Feature feature in cell.Features)
                        foreach (string resName in feature.PossibleRessources)
                            possibleResources.Add(Provider.GetRessource(resName));

                    List<MapRegion> regions = this.GetRegions(x, y);

                    foreach (MapRegion mr in regions)
                    {
                        foreach (string resName in mr.RessourceExcludes)
                            if (possibleResources.Count( a => a.Name == resName ) > 0 )
                                possibleResources.RemoveAll(a => a.Name == resName);
                    }

                    // if we have any possible there is a 20% chance to place a resource
                    if (possibleResources.Count > 0 && rnd.NextDouble() < 0.2)
                    {
                        PropabilityMap<Ressource> map = new PropabilityMap<Ressource>();

                        foreach (Ressource r in possibleResources)
                            map.AddItem(r, 1);

                        cell.SetRessources(map.Random);
                    }
                }
            }
        }