File: natives.py

package info (click to toggle)
freeorion 0.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 194,940 kB
  • sloc: cpp: 186,508; python: 40,969; ansic: 1,164; xml: 719; makefile: 32; sh: 7
file content (121 lines) | stat: -rw-r--r-- 6,183 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import freeorion as fo
import itertools
import random

import planets
import universe_statistics
import universe_tables

natives_for_planet_type = {}
planet_types_for_natives = {}


def generate_natives(native_freq, systems, empire_home_systems):  # noqa: C901
    """
    Adds non-empire-affiliated native populations to planets.
    And to asteroids and to gasgiants as well.
    """

    # first, calculate the chance for natives based on the native frequency that has been passed
    # get the corresponding value for the specified natives frequency from the universe tables
    native_chance = universe_tables.NATIVE_FREQUENCY[native_freq]
    # a value of 0 means no natives, in this case return immediately
    if native_chance <= 0:
        return

    # compile a list of systems where natives can be placed
    # select only systems sufficiently far away from player home systems
    # list of systems safe for natives
    EMPIRE_TO_NATIVE_MIN_DIST = 2
    empire_exclusions = set(
        itertools.chain.from_iterable(
            fo.systems_within_jumps_unordered(EMPIRE_TO_NATIVE_MIN_DIST, [e]) for e in empire_home_systems
        )
    )
    native_safe_planets = set(
        itertools.chain.from_iterable([fo.sys_get_planets(s) for s in systems if s not in empire_exclusions])
    )

    print("Number of planets far enough from players for natives to be allowed:", len(native_safe_planets))
    # if there are no "native safe" planets at all, we can stop here
    if not native_safe_planets:
        return

    # get all native species
    native_species = fo.get_native_species()
    print("Species that can be added as natives:")
    print("... " + "\n... ".join(native_species))

    # create a map with a list for each planet type containing the species
    # for which this planet type is a good environment
    # we will need this afterwards when picking natives for a planet
    natives_for_planet_type.clear()  # just to be safe
    natives_for_planet_type.update({planet_type: [] for planet_type in planets.planet_types})
    planet_types_for_natives.clear()
    planet_types_for_natives.update({species: set() for species in native_species})

    # iterate over all native species we got
    for species in native_species:
        # check the planet environment for all planet types for this species
        for planet_type in planets.planet_types:
            # if this planet type is a good environment for the species, add it to the list for this planet type
            if fo.species_get_planet_environment(species, planet_type) == fo.planetEnvironment.good:
                natives_for_planet_type[planet_type].append(species)
                planet_types_for_natives[species].add(planet_type)
        # if the species simply has no good environment to live in, try the same as above for adequate instead
        # this is needed for a couple of new native species with only adequate and no good environments
        if len(planet_types_for_natives[species]) < 1:
            for planet_type in planets.planet_types:
                if fo.species_get_planet_environment(species, planet_type) == fo.planetEnvironment.adequate:
                    natives_for_planet_type[planet_type].append(species)
                    planet_types_for_natives[species].add(planet_type)
        # if the species still has no fitting environment then try poor next
        if len(planet_types_for_natives[species]) < 1:
            for planet_type in planets.planet_types:
                if fo.species_get_planet_environment(species, planet_type) == fo.planetEnvironment.poor:
                    natives_for_planet_type[planet_type].append(species)
                    planet_types_for_natives[species].add(planet_type)

    # randomly add species to planets
    # iterate over the list of "native safe" planets we compiled earlier
    for candidate in native_safe_planets:
        # select a native species to put on this planet
        planet_type = fo.planet_get_type(candidate)
        # check if we have any native species that like this planet type
        if not natives_for_planet_type[planet_type]:
            # no, continue with next planet
            continue
        universe_statistics.potential_native_planet_summary[planet_type] += 1
        # temporarily dampen native frequencies on roids and GGs until better galaxy setup options are in place
        factor = 1
        if planet_type in [fo.planetType.asteroids, fo.planetType.gasGiant]:
            factor = 5
        # make a "roll" against the chance for natives to determine if we shall place natives on this planet
        if random.random() > native_chance / factor:
            # no, continue with next planet
            continue
        universe_statistics.settled_native_planet_summary[planet_type] += 1

        # randomly pick one of the native species available for this planet type
        natives = random.choice(natives_for_planet_type[planet_type])

        # put the selected natives on the planet
        fo.planet_set_species(candidate, natives)
        # set planet as homeworld for that species
        fo.species_add_homeworld(natives, candidate)
        # set planet focus
        # check if the preferred focus for the native species is among the foci available on this planet
        available_foci = fo.planet_available_foci(candidate)
        preferred_focus = fo.species_preferred_focus(natives)
        if preferred_focus in available_foci:
            # if yes, set the planet focus to the preferred focus
            fo.planet_set_focus(candidate, preferred_focus)
        elif available_foci:
            # if no, and there is at least one available focus, just take the first of the list
            # otherwise don't set any focus
            fo.planet_set_focus(candidate, available_foci[0])
            print("preferred focus", preferred_focus, "not available, focus on", available_foci[0], "instead")
        print("Added native", natives, "to planet", fo.get_name(candidate))

        # increase the statistics counter for this native species, so a species summary can be dumped to the log later
        universe_statistics.species_summary[natives] += 1