Passed
Pull Request — master (#226)
by Marek
01:53
created

AIs.ais_renegade.Renegade.economy_manager()   B

Complexity

Conditions 7

Size

Total Lines 20
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 18
nop 1
dl 0
loc 20
rs 8
c 0
b 0
f 0
1
#
2
#  Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/]
3
#
4
#  This file is part of Outer Space.
5
#
6
#  Outer Space is free software; you can redistribute it and/or modify
7
#  it under the terms of the GNU General Public License as published by
8
#  the Free Software Foundation; either version 2 of the License, or
9
#  (at your option) any later version.
10
#
11
#  Outer Space is distributed in the hope that it will be useful,
12
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#  GNU General Public License for more details.
15
#
16
#  You should have received a copy of the GNU General Public License
17
#  along with Outer Space; if not, write to the Free Software
18
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
#
20
import random
21
22
from ige import log
23
from ige.ospace import Const
24
from ige.ospace import Rules
25
26
from ais_base import AI
27
import ai_tools as tool
28
29
30
class Renegade(AI):
31
    """ Renegade is purely defensive AI, very static. It allows CP pacts and refuel
32
    for civilian ships, and has 5 pregenerated designs.
33
34
    1: Fighter [Small hull, Cockpit, 1x Cannon, 2x STL Engine]
35
    2: Corvette [Small hull, Cockpit, 2x Cannon, 1x Steel Armor, 1x STL Engine]
36
    3: Frigate [Medium hull, Bridge, 2x Cannon, 2x SS Rocket, 2x STL Engine]
37
    special using uranium:
38
    4: Destroyer [Medium hull, Bridge, 4x Cannon, 2x SS Rocket, 3x Nuclear STL Engine]
39
    special using titanium:
40
    5: Frigate [Crude Titanium Medium hull, Bridge, 5x Cannon, 3x SS Rocket, 4x STL Engine]
41
    """
42
43
    def _build_special_ships(self, planet):
44
        uranium_spec = self.player.shipDesigns[4]
45
        titanium_spec = self.player.shipDesigns[5]
46
        if self.player.stratRes.get(Const.SR_TL1A, 0) >= uranium_spec.buildSRes[Const.SR_TL1A]:
47
            planet.prodQueue, self.player.stratRes = self.client.cmdProxy.startConstruction(planet.oid, 4, 1, planet.oid, True, False, Const.OID_NONE)
48
            return True
49
        elif self.player.stratRes.get(Const.SR_TL1B, 0) >= titanium_spec.buildSRes[Const.SR_TL1B]:
50
            planet.prodQueue, self.player.stratRes = self.client.cmdProxy.startConstruction(planet.oid, 5, 1, planet.oid, True, False, Const.OID_NONE)
51
            return True
52
53
    def _build_normal_ships(self, planet):
54
            ship_draw = random.randint(1, 10)
55
            # if there is enough special resources for our unique designs, build those!
56
            # 1/10 - Frigate
57
            # 3/10 - Corvette
58
            # 6/10 - Fighter
59
            if ship_draw == 1:
60
                planet.prodQueue, self.player.stratRes = self.client.cmdProxy.startConstruction(planet.oid, 3, 1, planet.oid, True, False, Const.OID_NONE)
61
            elif ship_draw <= 4:
62
                planet.prodQueue, self.player.stratRes = self.client.cmdProxy.startConstruction(planet.oid, 2, 1, planet.oid, True, False, Const.OID_NONE)
63
            else:
64
                planet.prodQueue, self.player.stratRes = self.client.cmdProxy.startConstruction(planet.oid, 1, 1, planet.oid, True, False, Const.OID_NONE)
65
66
    def _build_ships(self, idle_planets):
67
        for planet_id in idle_planets:
68
            planet = self.db[planet_id]
69
            if self._build_special_ships(planet):
70
                continue
71
            self._build_normal_ships(planet)
72
73
    def _prepare_planet_plan(self, actual_stats, planet_id):
74
        planet = self.db[planet_id]
75
        if Rules.Tech.RENEGADECOSMODROME in actual_stats.planets[planet_id] or\
76
                Rules.Tech.RENEGADEBASE3 in actual_stats.planets[planet_id] or\
77
                Rules.Tech.RENEGADEBASE3MINOR in actual_stats.planets[planet_id]:
78
            return {Rules.Tech.RENEGADEBASE3:1,
79
                    Rules.Tech.RENEGADECOSMODROME:min(planet.plSlots - 1, 1),
80
                    Rules.Tech.RENEGADEBASE3MINOR:max(planet.plSlots - 2, 0)}
81
        elif planet.plStratRes and\
82
                tool.compareBuildStructPlans(actual_stats.planets[planet_id], {
83
                                            Rules.Tech.RENEGADEBASE2:1,
84
                                            Rules.Tech.RENEGADEBASE2MINOR:planet.plSlots - 1}):
85
            return {Rules.Tech.RENEGADEBASE3:1,
86
                    Rules.Tech.RENEGADEBASE2MINOR:planet.plSlots - 1}
87
        elif Rules.Tech.RENEGADEBASE2 in actual_stats.planets[planet_id]:
88
            return {Rules.Tech.RENEGADEBASE2:1,
89
                    Rules.Tech.RENEGADEBASE2MINOR:planet.plSlots - 1}
90
        elif actual_stats.planets[planet_id].setdefault(Rules.Tech.RENEGADEBASE, 0) > 0:
91
            planet.prodQueue, self.player.stratRes = \
92
                    self.client.cmdProxy.startConstruction(planet_id, Rules.Tech.RENEGADEBASE2,
93
                                                      1, planet_id, False, False, Rules.Tech.RENEGADEBASE)
94
            return actual_stats.planets[planet_id]
95
        else:
96
            return {Rules.Tech.RENEGADEBASE:1}
97
98
    def economy_manager(self):
99
        for planet_id in self.data.myPlanets:
100
            tool.sortStructures(self.client, self.db, planet_id)
101
        for system_id in self.data.mySystems:
102
            system = self.db[system_id]
103
            # creation of final system plans
104
            final_system_plan = {}
105
            actual_stats = tool.getSystemStructStats(self.data, self.client, self.db, system_id)
106
            build_stats = tool.getSystemStructStats(self.data, self.client, self.db, system_id, False)
107
            for planet_id in (self.data.myPlanets | self.data.freePlanets) & set(system.planets):
108
                final_system_plan[planet_id] = self._prepare_planet_plan(actual_stats, planet_id)
109
            idle_planets = tool.buildSystem(self.data, self.client, self.db, system_id, self.data.myProdPlanets & set(system.planets), final_system_plan)
110
            # build ships just in case cosmodrome is present, or being build, in the system
111
            has_cosmodrome = False
112
            for planet_id in self.data.myPlanets & set(system.planets):
113
                if Rules.Tech.RENEGADECOSMODROME in build_stats.planets[planet_id]:
114
                    has_cosmodrome = True
115
                    break
116
            if has_cosmodrome:
117
                self._build_ships(idle_planets)
118
119
    def diplomacy_manager(self):
120
        # renegades are friendly, want to trade, and can help refuel civilian ships
121
        for contact_id in self.player.diplomacyRels:
122
            dipl = self.client.getDiplomacyWith(contact_id)
123
            for pact_id in [Const.PACT_ALLOW_CIVILIAN_SHIPS, Const.PACT_ALLOW_TANKING, Const.PACT_MINOR_CP_COOP, Const.PACT_MAJOR_CP_COOP]:
124
                pact_spec = Rules.pactDescrs[pact_id]
125
                if dipl.relation < pact_spec.validityInterval[0] or dipl.relation > pact_spec.validityInterval[1]:
126
                    # not friendly enough
127
                    continue
128
                if pact_id in dipl.pacts and dipl.pacts[pact_id][0] in [Const.PACT_ACTIVE, Const.PACT_INACTIVE]:
129
                    # nothing more to do, move along
130
                    continue
131
                # hey, we should enable this pact!
132
                conditions = [pact_id]
133
                self.player.diplomacyRels = self.client.cmdProxy.changePactCond(self.player.oid, contact_id, pact_id, Const.PACT_INACTIVE, conditions)
134
135
    def run(self):
136
        self.economy_manager()
137
        self.diplomacy_manager()
138
139
140
def run(aclient):
141
    ai = Renegade(aclient)
142
    ai.run()
143
    aclient.saveDB()
144
145