File: calculate_population.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 (146 lines) | stat: -rw-r--r-- 6,461 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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import freeOrionAIInterface as fo

import AIDependencies
from AIDependencies import (
    POP_CONST_MOD_MAP,
    POP_SIZE_MOD_MAP_MODIFIED_BY_SPECIES,
    POP_SIZE_MOD_MAP_NOT_MODIFIED_BY_SPECIES,
)
from colonization.colony_score import debug_rating
from freeorion_tools import get_species_population, tech_is_complete

active_growth_specials = {}


def calc_max_pop(planet, species, detail):  # noqa: C901
    planet_size = planet.habitableSize
    planet_env = species.getPlanetEnvironment(planet.type)
    if planet_env == fo.planetEnvironment.uninhabitable:
        detail.append("Uninhabitable.")
        return 0

    for bldg_id in planet.buildingIDs:
        building = fo.getUniverse().getBuilding(bldg_id)
        if not building:
            continue
        if building.buildingTypeName == "BLD_GATEWAY_VOID":
            detail.append("Gateway to the void: Uninhabitable.")
            return 0

    if planet.speciesName in AIDependencies.SPECIES_FIXED_POPULATION:
        return AIDependencies.SPECIES_FIXED_POPULATION[planet.speciesName]

    tag_list = list(species.tags) if species else []
    pop_tag_mod = get_species_population(species.name)
    if planet.type == fo.planetType.gasGiant and "GASEOUS" in tag_list:
        gaseous_adjustment = AIDependencies.GASEOUS_POP_FACTOR
        detail.append("GASEOUS adjustment: %.2f" % gaseous_adjustment)
    else:
        gaseous_adjustment = 1.0

    planet_specials = set(planet.specials)

    base_pop_modified_by_species = 0
    base_pop_not_modified_by_species = 0
    pop_const_mod = 0

    # first, account for the environment
    environment_mod = POP_SIZE_MOD_MAP_MODIFIED_BY_SPECIES["environment_bonus"][planet_env]
    detail.append("Base environment: %d" % environment_mod)
    base_pop_modified_by_species += environment_mod

    # find all applicable modifiers
    for tech in POP_SIZE_MOD_MAP_MODIFIED_BY_SPECIES:
        if tech != "environment_bonus" and tech_is_complete(tech):
            base_pop_modified_by_species += POP_SIZE_MOD_MAP_MODIFIED_BY_SPECIES[tech][planet_env]
            detail.append("%s_PSM_early(%d)" % (tech, POP_SIZE_MOD_MAP_MODIFIED_BY_SPECIES[tech][planet_env]))

    for tech in POP_SIZE_MOD_MAP_NOT_MODIFIED_BY_SPECIES:
        if tech_is_complete(tech):
            base_pop_not_modified_by_species += POP_SIZE_MOD_MAP_NOT_MODIFIED_BY_SPECIES[tech][planet_env]
            detail.append("%s_PSM_late(%d)" % (tech, POP_SIZE_MOD_MAP_NOT_MODIFIED_BY_SPECIES[tech][planet_env]))

    for tech in POP_CONST_MOD_MAP:
        if tech_is_complete(tech):
            pop_const_mod += POP_CONST_MOD_MAP[tech][planet_env]
            detail.append("%s_PCM(%d)" % (tech, POP_CONST_MOD_MAP[tech][planet_env]))

    for _special in planet_specials.intersection(AIDependencies.POP_FIXED_MOD_SPECIALS):
        if AIDependencies.not_affect_by_special(_special, species.name):
            continue
        this_mod = AIDependencies.POP_FIXED_MOD_SPECIALS[_special]
        detail.append("%s_PCM(%d)" % (_special, this_mod))
        pop_const_mod += this_mod

    for _special in planet_specials.intersection(AIDependencies.POP_PROPORTIONAL_MOD_SPECIALS):
        this_mod = AIDependencies.POP_PROPORTIONAL_MOD_SPECIALS[_special]
        detail.append(f"{_special} (maxPop{this_mod:+.1f})")
        base_pop_not_modified_by_species += this_mod

    gaia = AIDependencies.GAIA_SPECIAL
    if gaia in planet_specials and not AIDependencies.not_affect_by_special(gaia, species):
        base_pop_not_modified_by_species += 3
        detail.append("Gaia_PSM_late(3)")

    if "SELF_SUSTAINING" in tag_list:
        if planet_env == fo.planetEnvironment.good:
            base_pop_not_modified_by_species += 3
            detail.append("SelfSustaining_PSM_late(3)")

    applicable_boosts = set()
    for this_tag in [tag for tag in tag_list if tag in AIDependencies.metabolismBoostMap]:
        metab_boosts = AIDependencies.metabolismBoostMap.get(this_tag, [])
        for key in active_growth_specials.keys():
            if len(active_growth_specials[key]) > 0 and key in metab_boosts:
                applicable_boosts.add(key)
                detail.append("%s boost active" % key)
        for boost in metab_boosts:
            if boost in planet_specials:
                applicable_boosts.add(boost)
                detail.append("%s boost present" % boost)

    n_boosts = len(applicable_boosts)
    if n_boosts:
        base_pop_not_modified_by_species += n_boosts
        detail.append("boosts_PSM(%d from %s)" % (n_boosts, applicable_boosts))

    if planet.id in species.homeworlds:
        detail.append("Homeworld (2)")
        base_pop_not_modified_by_species += 2

    if AIDependencies.TAG_LIGHT_SENSITIVE in tag_list:
        star_type = fo.getUniverse().getSystem(planet.systemID).starType
        star_pop_mod = AIDependencies.POP_MOD_LIGHTSENSITIVE_STAR_MAP.get(star_type, 0)
        base_pop_not_modified_by_species += star_pop_mod
        detail.append("Lightsensitive Star Bonus_PSM_late(%.1f)" % star_pop_mod)

    def max_pop_size():
        species_effect = (pop_tag_mod - 1) * abs(base_pop_modified_by_species)
        gaseous_effect = (gaseous_adjustment - 1) * abs(base_pop_modified_by_species)
        base_pop = base_pop_not_modified_by_species + base_pop_modified_by_species + species_effect + gaseous_effect
        return planet_size * base_pop + pop_const_mod

    target_pop = max_pop_size()
    if "PHOTOTROPHIC" in tag_list and target_pop > 0:
        star_type = fo.getUniverse().getSystem(planet.systemID).starType
        star_pop_mod = AIDependencies.POP_MOD_PHOTOTROPHIC_STAR_MAP.get(star_type, 0)
        base_pop_not_modified_by_species += star_pop_mod
        detail.append("Phototropic Star Bonus_PSM_late(%0.1f)" % star_pop_mod)
        target_pop = max_pop_size()

    detail.append("max_pop = base + size*[psm_early + species_mod*abs(psm_early) + psm_late]")
    detail.append(
        "        = %.2f + %d * [%.2f + %.2f*abs(%.2f) + %.2f]"
        % (
            pop_const_mod,
            planet_size,
            base_pop_modified_by_species,
            (pop_tag_mod + gaseous_adjustment - 2),
            base_pop_modified_by_species,
            base_pop_not_modified_by_species,
        )
    )
    detail.append("        = %.2f" % target_pop)
    # new rating code passes a dummy to this function and only adds the result to detail
    debug_rating(f"Details from calc_max_pop: {detail}")
    return target_pop