-
Notifications
You must be signed in to change notification settings - Fork 160
/
universe_generator.py
executable file
·147 lines (124 loc) · 5.82 KB
/
universe_generator.py
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
147
import random
import freeorion as fo
from starnames import name_star_systems
from galaxy import calc_star_system_positions
from starsystems import name_planets, generate_systems
from empires import compile_home_system_list, setup_empire
from fields import generate_fields
from natives import generate_natives
from monsters import generate_monsters
from specials import distribute_specials
from util import int_hash, seed_rng, report_error, error_list
from universe_tables import MAX_JUMPS_BETWEEN_SYSTEMS, MAX_STARLANE_LENGTH
import statistics
class PyGalaxySetupData:
"""
Class used to store and manage a copy of the galaxy setup data provided by the FreeOrion interface.
This data can then be modified when needed during the universe generation process, without having to
change the original data structure.
"""
def __init__(self, galaxy_setup_data):
self.seed = galaxy_setup_data.seed
self.size = galaxy_setup_data.size
self.shape = galaxy_setup_data.shape
self.age = galaxy_setup_data.age
self.starlane_frequency = galaxy_setup_data.starlaneFrequency
self.planet_density = galaxy_setup_data.planetDensity
self.specials_frequency = galaxy_setup_data.specialsFrequency
self.monster_frequency = galaxy_setup_data.monsterFrequency
self.native_frequency = galaxy_setup_data.nativeFrequency
self.max_ai_aggression = galaxy_setup_data.maxAIAggression
def error_report():
"""
Can be called from C++ to retrieve a list of errors that occurred during universe generation
"""
return error_list
def create_universe(psd_map):
"""
Main universe generation function invoked from C++ code.
"""
print "Python Universe Generator"
# fetch universe and player setup data
gsd = PyGalaxySetupData(fo.get_galaxy_setup_data())
total_players = len(psd_map)
# initialize RNG
h = int_hash(gsd.seed)
print "Using hashed seed", h
seed_rng(h)
seed_pool = [random.random() for _ in range(100)]
print "Seed pool:", seed_pool
# make sure there are enough systems for the given number of players
print "Universe creation requested with %d systems for %d players" % (gsd.size, total_players)
min_size = total_players * 3
if min_size > gsd.size:
gsd.size = min_size
print "Too few systems for the requested number of players, number of systems adjusted accordingly"
print "Creating universe with %d systems for %d players" % (gsd.size, total_players)
# calculate star system positions
seed_rng(seed_pool.pop())
system_positions = calc_star_system_positions(gsd)
size = len(system_positions)
print gsd.shape, "Star system positions calculated, final number of systems:", size
# generate and populate systems
seed_rng(seed_pool.pop())
systems = generate_systems(system_positions, gsd)
print len(systems), "systems generated and populated"
# generate Starlanes
seed_rng(seed_pool.pop())
fo.generate_starlanes(MAX_JUMPS_BETWEEN_SYSTEMS[gsd.starlane_frequency], MAX_STARLANE_LENGTH)
print "Starlanes generated"
print "Compile list of home systems..."
seed_rng(seed_pool.pop())
home_systems = compile_home_system_list(total_players, systems, gsd)
if not home_systems:
err_msg = "Python create_universe: couldn't get any home systems, ABORTING!"
report_error(err_msg)
raise Exception(err_msg)
print "Home systems:", home_systems
# set up empires for each player
seed_rng(seed_pool.pop())
for empire, psd, home_system in zip(psd_map.keys(), psd_map.values(), home_systems):
if not setup_empire(empire, psd.empire_name, home_system, psd.starting_species, psd.player_name):
report_error("Python create_universe: couldn't set up empire for player %s" % psd.player_name)
# assign names to all star systems and their planets
# this needs to be done after all systems have been generated and empire home systems have been set, as
# only after all that is finished star types as well as planet sizes and types are fixed, and the naming
# process depends on that
print "Assign star system names"
seed_rng(seed_pool.pop())
name_star_systems(systems)
print "Set planet names"
for system in systems:
name_planets(system)
print "Generating stationary fields in systems"
seed_rng(seed_pool.pop())
generate_fields(systems)
print "Generating Natives"
seed_rng(seed_pool.pop())
generate_natives(gsd.native_frequency, systems, home_systems)
print "Generating Space Monsters"
seed_rng(seed_pool.pop())
generate_monsters(gsd.monster_frequency, systems)
print "Distributing Starting Specials"
seed_rng(seed_pool.pop())
distribute_specials(gsd.specials_frequency, fo.get_all_objects())
# finally, write some statistics to the log file
print "############################################################"
print "## Universe generation statistics ##"
print "############################################################"
statistics.log_planet_count_dist(systems)
print "############################################################"
statistics.log_planet_type_summary(systems)
print "############################################################"
statistics.log_species_summary(gsd.native_frequency)
print "############################################################"
statistics.log_monsters_summary(gsd.monster_frequency)
print "############################################################"
statistics.log_specials_summary()
print "############################################################"
if error_list:
print "Python Universe Generator completed with errors"
return False
else:
print "Python Universe Generator completed successfully"
return True