def generate_systems(pos_list, gsd): """ Generates and populates star systems at all positions in specified list. """ sys_list = [] for position in pos_list: star_type = pick_star_type(gsd.age) system = fo.create_system(star_type, "", position.x, position.y) if system == fo.invalid_object(): # create system failed, report an error and try to continue with next position util.report_error( "Python generate_systems: create system at position (%f, %f) failed" % (position.x, position.y)) continue sys_list.append(system) for orbit in range(fo.sys_get_num_orbits(system)): # check for each orbit if a planet shall be created by determining planet size planet_size = planets.calc_planet_size(star_type, orbit, gsd.planetDensity, gsd.shape) if planet_size in planets.planet_sizes: # ok, we want a planet, determine planet type and generate the planet planet_type = planets.calc_planet_type(star_type, orbit, planet_size) if fo.create_planet(planet_size, planet_type, system, orbit, "") == fo.invalid_object(): # create planet failed, report an error and try to continue with next orbit util.report_error( "Python generate_systems: create planet in system %d failed" % system) return sys_list
def compile_home_system_list(num_home_systems, systems): """ Compiles a list with a requested number of home systems. """ # if the list of systems to choose home systems from is empty, report an error and return empty list if not systems: util.report_error("Python generate_home_system_list: no systems to choose from") return [] # calculate an initial minimal number of jumps that the home systems should be apart, # based on the total number of systems to choose from and the requested number of home systems min_jumps = max(int(float(len(systems)) / float(num_home_systems * 2)), 5) # try to find the home systems, decrease the min jumps until enough systems can be found, or the min jump distance # gets reduced to 0 (meaning we don't have enough systems to choose from at all) while min_jumps > 0: print "Trying to find", num_home_systems, "home systems that are at least", min_jumps, "jumps apart" # try to find home systems... home_systems = find_systems_with_min_jumps_between(num_home_systems, systems, min_jumps) # ...check if we got enough... if len(home_systems) >= num_home_systems: # ...yes, we got what we need, so let's break out of the loop break print "Home system min jump conflict: %d systems and %d empires, tried %d min jump and failed"\ % (len(systems), num_home_systems, min_jumps) # ...no, decrease the min jump distance and try again min_jumps -= 1 # check if the loop above delivered a list with enough home systems, or if it exited because the min jump distance # has been decreased to 0 without finding enough systems # in that case, our galaxy obviously is too crowded, report an error and return an empty list if len(home_systems) < num_home_systems: util.report_error("Python generate_home_system_list: requested %d homeworlds in a galaxy with %d systems" % (num_home_systems, len(systems))) return [] # make sure all our home systems have a "real" star (that is, a star that is not a neutron star, black hole, # or even no star at all) and at least one planet in it for home_system in home_systems: # if this home system has no "real" star, change star type to a randomly selected "real" star if fo.sys_get_star_type(home_system) not in starsystems.star_types_real: star_type = random.choice(starsystems.star_types_real) print "Home system", home_system, "has star type", fo.sys_get_star_type(home_system),\ ", changing that to", star_type fo.sys_set_star_type(home_system, star_type) # if this home system has no planets, create one in a random orbit # we take random values for type and size, as these will be set to suitable values later if not fo.sys_get_planets(home_system): print "Home system", home_system, "has no planets, adding one" planet = fo.create_planet(random.choice(planets.planet_sizes_real), random.choice(planets.planet_types_real), home_system, random.randint(0, fo.sys_get_num_orbits(home_system) - 1), "") # if we couldn't create the planet, report an error and return an empty list if planet == fo.invalid_object(): util.report_error("Python generate_home_system_list: couldn't create planet in home system") return [] return home_systems
def generate_a_planet(system, star_type, orbit, planet_density, galaxy_shape): """ Place a planet in an orbit of a system. Return True on success """ planet_size = calc_planet_size(star_type, orbit, planet_density, galaxy_shape) if planet_size not in planet_sizes: return False # ok, we want a planet, determine planet type and generate the planet planet_type = calc_planet_type(star_type, orbit, planet_size) if planet_type == fo.planetType.unknown: return False if fo.create_planet(planet_size, planet_type, system, orbit, "") == fo.invalid_object(): # create planet failed, report an error util.report_error("Python generate_systems: create planet in system %d failed" % system) return False return True
def generate_a_planet(system, star_type, orbit, planet_density, galaxy_shape): """ Place a planet in an orbit of a system. Return True on success """ planet_size = calc_planet_size(star_type, orbit, planet_density, galaxy_shape) if planet_size not in planet_sizes: return False # ok, we want a planet, determine planet type and generate the planet planet_type = calc_planet_type(star_type, orbit, planet_size) if planet_type == fo.planetType.unknown: return False if fo.create_planet(planet_size, planet_type, system, orbit, "") == fo.invalid_object(): # create planet failed, report an error util.report_error( "Python generate_systems: create planet in system %d failed" % system) return False return True
def generate_systems(pos_list, gsd): """ Generates and populates star systems at all positions in specified list. """ sys_list = [] for position in pos_list: star_type = pick_star_type(gsd.age) system = fo.create_system(star_type, "", position.x, position.y) if system == fo.invalid_object(): # create system failed, report an error and try to continue with next position util.report_error("Python generate_systems: create system at position (%f, %f) failed" % (position.x, position.y)) continue sys_list.append(system) for orbit in range(0, fo.sys_get_num_orbits(system) - 1): # check for each orbit if a planet shall be created by determining planet size planet_size = planets.calc_planet_size(star_type, orbit, gsd.planetDensity, gsd.shape) if planet_size in planets.planet_sizes: # ok, we want a planet, determine planet type and generate the planet planet_type = planets.calc_planet_type(star_type, orbit, planet_size) if fo.create_planet(planet_size, planet_type, system, orbit, "") == fo.invalid_object(): # create planet failed, report an error and try to continue with next orbit util.report_error("Python generate_systems: create planet in system %d failed" % system) return sys_list
def compile_home_system_list(num_home_systems, systems, gsd): """ Compiles a list with a requested number of home systems. """ print "Compile home system list:", num_home_systems, "systems requested" # if the list of systems to choose home systems from is empty, report an error and return empty list if not systems: report_error( "Python generate_home_system_list: no systems to choose from") return [] # calculate an initial minimal number of jumps that the home systems should be apart, # based on the total number of systems to choose from and the requested number of home systems # don't let min_jumps be either: # a.) larger than a defined limit, because an unreasonably large number is really not at all needed, # and with large galaxies an excessive amount of time can be used in failed attempts # b.) lower than the minimum jump distance limit that should be considered high priority (see options.py), # otherwise no attempt at all would be made to enforce the other requirements for home systems (see below) min_jumps = min( HS_MAX_JUMP_DISTANCE_LIMIT, max(int(float(len(systems)) / float(num_home_systems * 2)), HS_MIN_DISTANCE_PRIORITY_LIMIT)) # home systems must have a certain minimum of systems and planets in their near vicinity # we will try to select our home systems from systems that match this criteria, if that fails, we will select our # home systems from all systems and add the missing number planets to the systems in their vicinity afterwards # the minimum system and planet limit and the jump range that defines the "near vicinity" are controlled by the # HS_* option constants in options.py (see there) # we start by building two additional pools of systems: one that contains all systems that match the criteria # completely (meets the min systems and planets limit), and one that contains all systems that match the criteria # at least partially (meets the min systems limit) pool_matching_sys_and_planet_limit = [] pool_matching_sys_limit = [] for system in systems: systems_in_vicinity = fo.systems_within_jumps_unordered( HS_VICINITY_RANGE, [system]) if len(systems_in_vicinity) >= HS_MIN_SYSTEMS_IN_VICINITY: pool_matching_sys_limit.append(system) if count_planets_in_systems( systems_in_vicinity) >= min_planets_in_vicinity_limit( len(systems_in_vicinity)): pool_matching_sys_and_planet_limit.append(system) print( len(pool_matching_sys_and_planet_limit), "systems meet the min systems and planets in the near vicinity limit") print len(pool_matching_sys_limit ), "systems meet the min systems in the near vicinity limit" # now try to pick the requested number of home systems # we will do this by calling find_home_systems, which takes a list of tuples defining the pools from which to pick # the home systems; it will use the pools in the order in which they appear in the list, so put better pools first # we will make two attempts: the first one with the filtered pools we just created, and tell find_home_systems # to start with the min_jumps jumps distance we calculated above, but not to go lower than # HS_MIN_DISTANCE_PRIORITY_LIMIT print "First attempt: trying to pick home systems from the filtered pools of preferred systems" pool_list = [ # the better pool is of course the one where all systems meet BOTH the min systems and planets limit (pool_matching_sys_and_planet_limit, "pool of systems that meet both the min systems and planets limit"), # next the less preferred pool where all systems at least meets the min systems limit # specify 0 as number of requested home systems to pick as much systems as possible (pool_matching_sys_limit, "pool of systems that meet at least the min systems limit"), ] home_systems = find_home_systems(num_home_systems, pool_list, min_jumps, HS_MIN_DISTANCE_PRIORITY_LIMIT) # check if the first attempt delivered a list with enough home systems # if not, we make our second attempt, this time disregarding the filtered pools and using all systems, starting # again with the min_jumps jump distance limit and specifying 0 as number of required home systems to pick as much # systems as possible if len(home_systems) < num_home_systems: print "Second attempt: trying to pick home systems from all systems" home_systems = find_home_systems(num_home_systems, [(systems, "complete pool")], min_jumps, 1) # check if the selection process delivered a list with enough home systems # if not, our galaxy obviously is too crowded, report an error and return an empty list if len(home_systems) < num_home_systems: report_error( "Python generate_home_system_list: requested %d homeworlds in a galaxy with %d systems" % (num_home_systems, len(systems))) return [] # check if we got more home systems than we requested if len(home_systems) > num_home_systems: # yes: calculate the number of planets in the near vicinity of each system # and store that value with each system in a map hs_planets_in_vicinity_map = { s: calculate_home_system_merit(s) for s in home_systems } # sort the home systems by the number of planets in their near vicinity using the map # now only pick the number of home systems we need, taking those with the highest number of planets home_systems = sorted(home_systems, key=hs_planets_in_vicinity_map.get, reverse=True)[:num_home_systems] # make sure all our home systems have a "real" star (that is, a star that is not a neutron star, black hole, # or even no star at all) and at least one planet in it for home_system in home_systems: # if this home system has no "real" star, change star type to a randomly selected "real" star if fo.sys_get_star_type(home_system) not in star_types_real: star_type = random.choice(star_types_real) print "Home system", home_system, "has star type", fo.sys_get_star_type(home_system),\ ", changing that to", star_type fo.sys_set_star_type(home_system, star_type) # if this home system has no planets, create one in a random orbit # we take random values for type and size, as these will be set to suitable values later if not fo.sys_get_planets(home_system): print "Home system", home_system, "has no planets, adding one" planet = fo.create_planet( random.choice(planet_sizes_real), random.choice(planet_types_real), home_system, random.randint(0, fo.sys_get_num_orbits(home_system) - 1), "") # if we couldn't create the planet, report an error and return an empty list if planet == fo.invalid_object(): report_error( "Python generate_home_system_list: couldn't create planet in home system" ) return [] # finally, check again if all home systems meet the criteria of having the required minimum number of planets # within their near vicinity, if not, add the missing number of planets print "Checking if home systems have the required minimum of planets within the near vicinity..." for home_system in home_systems: # calculate the number of missing planets, and add them if this number is > 0 systems_in_vicinity = fo.systems_within_jumps_unordered( HS_VICINITY_RANGE, [home_system]) num_systems_in_vicinity = len(systems_in_vicinity) num_planets_in_vicinity = count_planets_in_systems(systems_in_vicinity) num_planets_to_add = min_planets_in_vicinity_limit( num_systems_in_vicinity) - num_planets_in_vicinity print "Home system", home_system, "has", num_systems_in_vicinity, "systems and", num_planets_in_vicinity,\ "planets in the near vicinity, required minimum:", min_planets_in_vicinity_limit(num_systems_in_vicinity) if num_planets_to_add > 0: systems_in_vicinity.remove( home_system ) # don't add planets to the home system, so remove it from the list # sort the systems_in_vicinity before adding, since the C++ engine doesn't guarrantee the same # platform independence as python. add_planets_to_vicinity(sorted(systems_in_vicinity), num_planets_to_add, gsd) # as we've sorted the home system list before, lets shuffle it to ensure random order and return random.shuffle(home_systems) return home_systems
def add_planets_to_vicinity(vicinity, num_planets, gsd): """ Adds the specified number of planets to the specified systems. """ print "Adding", num_planets, "planets to the following systems:", vicinity # first, compile a list containing all the free orbits in the specified systems # begin with adding the free orbits of all systems that have a real star (that is, no neutron star, black hole, # and not no star), if that isn't enough, also one, by one, add the free orbits of neutron star, black hole and # no star systems (in that order) until we have enough free orbits # for that, we use this list of tuples # the first tuple contains all real star types, the following tuples the neutron, black hole and no star types, # so we can iterate over this list and only add the free orbits of systems that match the respective star types # each step # this way we can prioritize the systems we want to add planets to by star type acceptable_star_types_list = [ star_types_real, (fo.starType.noStar, ), (fo.starType.neutron, ), (fo.starType.blackHole, ) ] # store the free orbits as a list of tuples of (system, orbit) free_orbits_map = [] # now, iterate over the list of acceptable star types for acceptable_star_types in acceptable_star_types_list: # check all systems in the list of systems we got passed into this function for system in vicinity: # if this system has a star type we want to accept in this step, add its free orbits to our list if fo.sys_get_star_type(system) in acceptable_star_types: free_orbits_map.extend([ (system, orbit) for orbit in fo.sys_free_orbits(system) ]) # check if we got enough free orbits after completing this step # we want 4 times as much free orbits as planets we want to add, that means each system shouldn't get more # than 2-3 additional planets on average if len(free_orbits_map) > (num_planets * 4): break # if we got less free orbits than planets that should be added, something is wrong # in that case abort and log an error if len(free_orbits_map) < num_planets: report_error( "Python add_planets_to_vicinity: less free orbits than planets to add - cancelled" ) print "...free orbits available:", free_orbits_map # as we will pop the free orbits from this list afterwards, shuffle it to randomize the order of the orbits random.shuffle(free_orbits_map) # add the requested number of planets while num_planets > 0: # get the next free orbit from the list we just compiled system, orbit = free_orbits_map.pop() # check the star type of the system containing the orbit we got star_type = fo.sys_get_star_type(system) if star_type in [fo.starType.noStar, fo.starType.blackHole]: # if it is a black hole or has no star, change the star type # pick a star type, continue until we get a real star # don't accept neutron, black hole or no star print "...system picked to add a planet has star type", star_type while star_type not in star_types_real: star_type = pick_star_type(gsd.age) print "...change that to", star_type fo.sys_set_star_type(system, star_type) # pick a planet size, continue until we get a size that matches the HS_ACCEPTABLE_PLANET_SIZES option planet_size = fo.planetSize.unknown while planet_size not in HS_ACCEPTABLE_PLANET_SIZES: planet_size = calc_planet_size(star_type, orbit, fo.galaxySetupOption.high, gsd.shape) # pick an according planet type planet_type = calc_planet_type(star_type, orbit, planet_size) # finally, create the planet in the system and orbit we got print "...adding", planet_size, planet_type, "planet to system", system if fo.create_planet(planet_size, planet_type, system, orbit, "") == fo.invalid_object(): report_error( "Python add_planets_to_vicinity: create planet in system %d failed" % system) # continue with next planet num_planets -= 1
def compile_home_system_list(num_home_systems, systems, gsd): """ Compiles a list with a requested number of home systems. """ print "Compile home system list:", num_home_systems, "systems requested" # if the list of systems to choose home systems from is empty, report an error and return empty list if not systems: report_error("Python generate_home_system_list: no systems to choose from") return [] # calculate an initial minimal number of jumps that the home systems should be apart, # based on the total number of systems to choose from and the requested number of home systems # don't let min_jumps be either: # a.) larger than a defined limit, because an unreasonably large number is really not at all needed, # and with large galaxies an excessive amount of time can be used in failed attempts # b.) lower than the minimum jump distance limit that should be considered high priority (see options.py), # otherwise no attempt at all would be made to enforce the other requirements for home systems (see below) min_jumps = min(HS_MAX_JUMP_DISTANCE_LIMIT, max(int(float(len(systems)) / float(num_home_systems * 2)), HS_MIN_DISTANCE_PRIORITY_LIMIT)) # home systems must have a certain minimum of systems and planets in their near vicinity # we will try to select our home systems from systems that match this criteria, if that fails, we will select our # home systems from all systems and add the missing number planets to the systems in their vicinity afterwards # the minimum system and planet limit and the jump range that defines the "near vicinity" are controlled by the # HS_* option constants in options.py (see there) # we start by building two additional pools of systems: one that contains all systems that match the criteria # completely (meets the min systems and planets limit), and one that contains all systems that match the criteria # at least partially (meets the min systems limit) pool_matching_sys_and_planet_limit = [] pool_matching_sys_limit = [] for system in systems: systems_in_vicinity = get_systems_within_jumps(system, HS_VICINITY_RANGE) if len(systems_in_vicinity) >= HS_MIN_SYSTEMS_IN_VICINITY: pool_matching_sys_limit.append(system) if count_planets_in_systems(systems_in_vicinity) >= min_planets_in_vicinity_limit(len(systems_in_vicinity)): pool_matching_sys_and_planet_limit.append(system) print len(pool_matching_sys_and_planet_limit), "systems meet the min systems and planets in the near vicinity limit" print len(pool_matching_sys_limit), "systems meet the min systems in the near vicinity limit" # now try to pick the requested number of home systems # we will do this by calling find_home_systems, which takes a list of tuples defining the pools from which to pick # the home systems; it will use the pools in the order in which they appear in the list, so put better pools first # we will make two attempts: the first one with the filtered pools we just created, and tell find_home_systems # to start with the min_jumps jumps distance we calculated above, but not to go lower than # HS_MIN_DISTANCE_PRIORITY_LIMIT print "First attempt: trying to pick home systems from the filtered pools of preferred systems" pool_list = [ # the better pool is of course the one where all systems meet BOTH the min systems and planets limit (pool_matching_sys_and_planet_limit, "pool of systems that meet both the min systems and planets limit"), # next the less preferred pool where all systems at least meets the min systems limit # specify 0 as number of requested home systems to pick as much systems as possible (pool_matching_sys_limit, "pool of systems that meet at least the min systems limit"), ] home_systems = find_home_systems(num_home_systems, pool_list, min_jumps, HS_MIN_DISTANCE_PRIORITY_LIMIT) # check if the first attempt delivered a list with enough home systems # if not, we make our second attempt, this time disregarding the filtered pools and using all systems, starting # again with the min_jumps jump distance limit and specifying 0 as number of required home systems to pick as much # systems as possible if len(home_systems) < num_home_systems: print "Second attempt: trying to pick home systems from all systems" home_systems = find_home_systems(num_home_systems, [(systems, "complete pool")], min_jumps, 1) # check if the selection process delivered a list with enough home systems # if not, our galaxy obviously is too crowded, report an error and return an empty list if len(home_systems) < num_home_systems: report_error("Python generate_home_system_list: requested %d homeworlds in a galaxy with %d systems" % (num_home_systems, len(systems))) return [] # check if we got more home systems than we requested if len(home_systems) > num_home_systems: # yes: calculate the number of planets in the near vicinity of each system # and store that value with each system in a map hs_planets_in_vicinity_map = {s: count_planets_in_systems(get_systems_within_jumps(s, HS_VICINITY_RANGE)) for s in home_systems} # sort the home systems by the number of planets in their near vicinity using the map # now only pick the number of home systems we need, taking those with the highest number of planets home_systems = sorted(home_systems, key=hs_planets_in_vicinity_map.get, reverse=True)[:num_home_systems] # make sure all our home systems have a "real" star (that is, a star that is not a neutron star, black hole, # or even no star at all) and at least one planet in it for home_system in home_systems: # if this home system has no "real" star, change star type to a randomly selected "real" star if fo.sys_get_star_type(home_system) not in star_types_real: star_type = random.choice(star_types_real) print "Home system", home_system, "has star type", fo.sys_get_star_type(home_system),\ ", changing that to", star_type fo.sys_set_star_type(home_system, star_type) # if this home system has no planets, create one in a random orbit # we take random values for type and size, as these will be set to suitable values later if not fo.sys_get_planets(home_system): print "Home system", home_system, "has no planets, adding one" planet = fo.create_planet(random.choice(planet_sizes_real), random.choice(planet_types_real), home_system, random.randint(0, fo.sys_get_num_orbits(home_system) - 1), "") # if we couldn't create the planet, report an error and return an empty list if planet == fo.invalid_object(): report_error("Python generate_home_system_list: couldn't create planet in home system") return [] # finally, check again if all home systems meet the criteria of having the required minimum number of planets # within their near vicinity, if not, add the missing number of planets print "Checking if home systems have the required minimum of planets within the near vicinity..." for home_system in home_systems: # calculate the number of missing planets, and add them if this number is > 0 systems_in_vicinity = get_systems_within_jumps(home_system, HS_VICINITY_RANGE) num_systems_in_vicinity = len(systems_in_vicinity) num_planets_in_vicinity = count_planets_in_systems(systems_in_vicinity) num_planets_to_add = min_planets_in_vicinity_limit(num_systems_in_vicinity) - num_planets_in_vicinity print "Home system", home_system, "has", num_systems_in_vicinity, "systems and", num_planets_in_vicinity,\ "planets in the near vicinity, required minimum:", min_planets_in_vicinity_limit(num_systems_in_vicinity) if num_planets_to_add > 0: systems_in_vicinity.remove(home_system) # don't add planets to the home system, so remove it from the list add_planets_to_vicinity(systems_in_vicinity, num_planets_to_add, gsd) # as we've sorted the home system list before, lets shuffle it to ensure random order and return random.shuffle(home_systems) return home_systems
def add_planets_to_vicinity(vicinity, num_planets, gsd): """ Adds the specified number of planets to the specified systems. """ print "Adding", num_planets, "planets to the following systems:", vicinity # first, compile a list containing all the free orbits in the specified systems # begin with adding the free orbits of all systems that have a real star (that is, no neutron star, black hole, # and not no star), if that isn't enough, also one, by one, add the free orbits of neutron star, black hole and # no star systems (in that order) until we have enough free orbits # for that, we use this list of tuples # the first tuple contains all real star types, the following tuples the neutron, black hole and no star types, # so we can iterate over this list and only add the free orbits of systems that match the respective star types # each step # this way we can prioritize the systems we want to add planets to by star type acceptable_star_types_list = [ star_types_real, (fo.starType.noStar,), (fo.starType.neutron,), (fo.starType.blackHole,) ] # store the free orbits as a list of tuples of (system, orbit) free_orbits_map = [] # now, iterate over the list of acceptable star types for acceptable_star_types in acceptable_star_types_list: # check all systems in the list of systems we got passed into this function for system in vicinity: # if this system has a star type we want to accept in this step, add its free orbits to our list if fo.sys_get_star_type(system) in acceptable_star_types: free_orbits_map.extend([(system, orbit) for orbit in fo.sys_free_orbits(system)]) # check if we got enough free orbits after completing this step # we want 4 times as much free orbits as planets we want to add, that means each system shouldn't get more # than 2-3 additional planets on average if len(free_orbits_map) > (num_planets * 4): break # if we got less free orbits than planets that should be added, something is wrong # in that case abort and log an error if len(free_orbits_map) < num_planets: report_error("Python add_planets_to_vicinity: less free orbits than planets to add - cancelled") print "...free orbits available:", free_orbits_map # as we will pop the free orbits from this list afterwards, shuffle it to randomize the order of the orbits random.shuffle(free_orbits_map) # add the requested number of planets while num_planets > 0: # get the next free orbit from the list we just compiled system, orbit = free_orbits_map.pop() # check the star type of the system containing the orbit we got star_type = fo.sys_get_star_type(system) if star_type in [fo.starType.noStar, fo.starType.blackHole]: # if it is a black hole or has no star, change the star type # pick a star type, continue until we get a real star # don't accept neutron, black hole or no star print "...system picked to add a planet has star type", star_type while star_type not in star_types_real: star_type = pick_star_type(gsd.age) print "...change that to", star_type fo.sys_set_star_type(system, star_type) # pick a planet size, continue until we get a size that matches the HS_ACCEPTABLE_PLANET_SIZES option planet_size = fo.planetSize.unknown while planet_size not in HS_ACCEPTABLE_PLANET_SIZES: planet_size = calc_planet_size(star_type, orbit, fo.galaxySetupOption.high, gsd.shape) # pick an according planet type planet_type = calc_planet_type(star_type, orbit, planet_size) # finally, create the planet in the system and orbit we got print "...adding", planet_size, planet_type, "planet to system", system if fo.create_planet(planet_size, planet_type, system, orbit, "") == fo.invalid_object(): report_error("Python add_planets_to_vicinity: create planet in system %d failed" % system) # continue with next planet num_planets -= 1
def compile_home_system_list(num_home_systems, systems): """ Compiles a list with a requested number of home systems. """ print "Compile home system list:", num_home_systems, "systems requested" # if the list of systems to choose home systems from is empty, report an error and return empty list if not systems: report_error( "Python generate_home_system_list: no systems to choose from") return [] # calculate an initial minimal number of jumps that the home systems should be apart, # based on the total number of systems to choose from and the requested number of home systems # Don't let min_jumps be larger than 10, because a larger number is really not at all needed and with large # galaxies an excessive amount of time can be used in failed attempts min_jumps = min( 10, max(int(float(len(systems)) / float(num_home_systems * 2)), 5)) # home systems must have a certain minimum of systems in their near vicinity # we will try to select our home systems from systems that match this criteria, if that fails, we will select our # home systems from all systems and add the missing number planets to the systems in their vicinity afterwards # the minimum planet limit and the jump range that defines the "near vicinity" are controlled by the # HS_* option constants in options.py (see there) # lets start by filtering out all systems from the pool we got passed into this function that match the criteria filtered_pool = [s for s in systems if has_min_planets_in_vicinity(s)] print "Filtering out systems that meet the minimum planets in the near vicinity condition yielded",\ len(filtered_pool), "systems" print "Using this as the preferred pool for home system selection" # now try to pick the requested number of home systems by calling find_home_systems # this function takes two pools, a "complete" pool and one with preferred systems # it will try to pick the home systems from the preferred pool first, so pass our filtered pool as preferred pool home_systems = find_home_systems(num_home_systems, systems, filtered_pool, min_jumps) # check if the selection process delivered a list with enough home systems # if not, our galaxy obviously is too crowded, report an error and return an empty list if len(home_systems) < num_home_systems: report_error( "Python generate_home_system_list: requested %d homeworlds in a galaxy with %d systems" % (num_home_systems, len(systems))) return [] # check if we got more home systems than we requested if len(home_systems) > num_home_systems: # yes: calculate the number of planets in the near vicinity of each system # and store that value with each system in a map hs_planets_in_vicinity_map = { s: count_planets_in_systems( get_systems_within_jumps(s, HS_VICINITY_RANGE)) for s in home_systems } # sort the home systems by the number of planets in their near vicinity using the map # now only pick the number of home systems we need, taking those with the highest number of planets home_systems = sorted(home_systems, key=hs_planets_in_vicinity_map.get, reverse=True)[:num_home_systems] # make sure all our home systems have a "real" star (that is, a star that is not a neutron star, black hole, # or even no star at all) and at least one planet in it for home_system in home_systems: # if this home system has no "real" star, change star type to a randomly selected "real" star if fo.sys_get_star_type(home_system) not in star_types_real: star_type = random.choice(star_types_real) print "Home system", home_system, "has star type", fo.sys_get_star_type(home_system),\ ", changing that to", star_type fo.sys_set_star_type(home_system, star_type) # if this home system has no planets, create one in a random orbit # we take random values for type and size, as these will be set to suitable values later if not fo.sys_get_planets(home_system): print "Home system", home_system, "has no planets, adding one" planet = fo.create_planet( random.choice(planet_sizes_real), random.choice(planet_types_real), home_system, random.randint(0, fo.sys_get_num_orbits(home_system) - 1), "") # if we couldn't create the planet, report an error and return an empty list if planet == fo.invalid_object(): report_error( "Python generate_home_system_list: couldn't create planet in home system" ) return [] # finally, check again if all home systems meet the criteria of having the required minimum number of planets # within their near vicinity, if not, add the missing number of planets print "Checking if home systems have the required minimum of planets within the near vicinity..." for home_system in home_systems: # calculate the number of missing planets, and add them if this number is > 0 systems_in_vicinity = get_systems_within_jumps(home_system, HS_VICINITY_RANGE) num_systems_in_vicinity = len(systems_in_vicinity) num_planets_in_vicinity = count_planets_in_systems(systems_in_vicinity) num_planets_to_add = min_planets_in_vicinity_limit( num_systems_in_vicinity) - num_planets_in_vicinity print "Home system", home_system, "has", num_systems_in_vicinity, "systems and", num_planets_in_vicinity,\ "planets in the near vicinity, required minimum:", min_planets_in_vicinity_limit(num_systems_in_vicinity) if num_planets_to_add > 0: systems_in_vicinity.remove( home_system ) # don't add planets to the home system, so remove it from the list add_planets_to_vicinity(systems_in_vicinity, num_planets_to_add) # as we've sorted the home system list before, lets shuffle it to ensure random order and return random.shuffle(home_systems) return home_systems
def compile_home_system_list(num_home_systems, systems): """ Compiles a list with a requested number of home systems. """ # if the list of systems to choose home systems from is empty, report an error and return empty list if not systems: util.report_error( "Python generate_home_system_list: no systems to choose from") return [] # calculate an initial minimal number of jumps that the home systems should be apart, # based on the total number of systems to choose from and the requested number of home systems min_jumps = max(int(float(len(systems)) / float(num_home_systems * 2)), 5) # try to find the home systems, decrease the min jumps until enough systems can be found, or the min jump distance # gets reduced to 0 (meaning we don't have enough systems to choose from at all) while min_jumps > 0: print "Trying to find", num_home_systems, "home systems that are at least", min_jumps, "jumps apart" # try to find home systems... home_systems = find_systems_with_min_jumps_between( num_home_systems, systems, min_jumps) # ...check if we got enough... if len(home_systems) >= num_home_systems: # ...yes, we got what we need, so let's break out of the loop break print "Home system min jump conflict: %d systems and %d empires, tried %d min jump and failed"\ % (len(systems), num_home_systems, min_jumps) # ...no, decrease the min jump distance and try again min_jumps -= 1 # check if the loop above delivered a list with enough home systems, or if it exited because the min jump distance # has been decreased to 0 without finding enough systems # in that case, our galaxy obviously is too crowded, report an error and return an empty list if len(home_systems) < num_home_systems: util.report_error( "Python generate_home_system_list: requested %d homeworlds in a galaxy with %d systems" % (num_home_systems, len(systems))) return [] # make sure all our home systems have a "real" star (that is, a star that is not a neutron star, black hole, # or even no star at all) and at least one planet in it for home_system in home_systems: # if this home system has no "real" star, change star type to a randomly selected "real" star if fo.sys_get_star_type( home_system) not in starsystems.star_types_real: star_type = random.choice(starsystems.star_types_real) print "Home system", home_system, "has star type", fo.sys_get_star_type(home_system),\ ", changing that to", star_type fo.sys_set_star_type(home_system, star_type) # if this home system has no planets, create one in a random orbit # we take random values for type and size, as these will be set to suitable values later if not fo.sys_get_planets(home_system): print "Home system", home_system, "has no planets, adding one" planet = fo.create_planet( random.choice(planets.planet_sizes_real), random.choice(planets.planet_types_real), home_system, random.randint(0, fo.sys_get_num_orbits(home_system) - 1), "") # if we couldn't create the planet, report an error and return an empty list if planet == fo.invalid_object(): util.report_error( "Python generate_home_system_list: couldn't create planet in home system" ) return [] return home_systems
def compile_home_system_list(num_home_systems, systems): """ Compiles a list with a requested number of home systems. """ print "Compile home system list:", num_home_systems, "systems requested" # if the list of systems to choose home systems from is empty, report an error and return empty list if not systems: report_error("Python generate_home_system_list: no systems to choose from") return [] # calculate an initial minimal number of jumps that the home systems should be apart, # based on the total number of systems to choose from and the requested number of home systems # Don't let min_jumps be larger than 10, because a larger number is really not at all needed and with large # galaxies an excessive amount of time can be used in failed attempts min_jumps = min(10, max(int(float(len(systems)) / float(num_home_systems * 2)), 5)) # home systems must have a certain minimum of systems in their near vicinity # we will try to select our home systems from systems that match this criteria, if that fails, we will select our # home systems from all systems and add the missing number planets to the systems in their vicinity afterwards # the minimum planet limit and the jump range that defines the "near vicinity" are controlled by the # HS_* option constants in options.py (see there) # lets start by filtering out all systems from the pool we got passed into this function that match the criteria filtered_pool = [s for s in systems if has_min_planets_in_vicinity(s)] print "Filtering out systems that meet the minimum planets in the near vicinity condition yielded",\ len(filtered_pool), "systems" print "Using this as the preferred pool for home system selection" # now try to pick the requested number of home systems by calling find_home_systems # this function takes two pools, a "complete" pool and one with preferred systems # it will try to pick the home systems from the preferred pool first, so pass our filtered pool as preferred pool home_systems = find_home_systems(num_home_systems, systems, filtered_pool, min_jumps) # check if the selection process delivered a list with enough home systems # if not, our galaxy obviously is too crowded, report an error and return an empty list if len(home_systems) < num_home_systems: report_error("Python generate_home_system_list: requested %d homeworlds in a galaxy with %d systems" % (num_home_systems, len(systems))) return [] # check if we got more home systems than we requested if len(home_systems) > num_home_systems: # yes: calculate the number of planets in the near vicinity of each system # and store that value with each system in a map hs_planets_in_vicinity_map = {s: count_planets_in_systems(get_systems_within_jumps(s, HS_VICINITY_RANGE)) for s in home_systems} # sort the home systems by the number of planets in their near vicinity using the map # now only pick the number of home systems we need, taking those with the highest number of planets home_systems = sorted(home_systems, key=hs_planets_in_vicinity_map.get, reverse=True)[:num_home_systems] # make sure all our home systems have a "real" star (that is, a star that is not a neutron star, black hole, # or even no star at all) and at least one planet in it for home_system in home_systems: # if this home system has no "real" star, change star type to a randomly selected "real" star if fo.sys_get_star_type(home_system) not in star_types_real: star_type = random.choice(star_types_real) print "Home system", home_system, "has star type", fo.sys_get_star_type(home_system),\ ", changing that to", star_type fo.sys_set_star_type(home_system, star_type) # if this home system has no planets, create one in a random orbit # we take random values for type and size, as these will be set to suitable values later if not fo.sys_get_planets(home_system): print "Home system", home_system, "has no planets, adding one" planet = fo.create_planet(random.choice(planet_sizes_real), random.choice(planet_types_real), home_system, random.randint(0, fo.sys_get_num_orbits(home_system) - 1), "") # if we couldn't create the planet, report an error and return an empty list if planet == fo.invalid_object(): report_error("Python generate_home_system_list: couldn't create planet in home system") return [] # finally, check again if all home systems meet the criteria of having the required minimum number of planets # within their near vicinity, if not, add the missing number of planets print "Checking if home systems have the required minimum of planets within the near vicinity..." for home_system in home_systems: # calculate the number of missing planets, and add them if this number is > 0 systems_in_vicinity = get_systems_within_jumps(home_system, HS_VICINITY_RANGE) num_systems_in_vicinity = len(systems_in_vicinity) num_planets_in_vicinity = count_planets_in_systems(systems_in_vicinity) num_planets_to_add = min_planets_in_vicinity_limit(num_systems_in_vicinity) - num_planets_in_vicinity print "Home system", home_system, "has", num_systems_in_vicinity, "systems and", num_planets_in_vicinity,\ "planets in the near vicinity, required minimum:", min_planets_in_vicinity_limit(num_systems_in_vicinity) if num_planets_to_add > 0: systems_in_vicinity.remove(home_system) # don't add planets to the home system, so remove it from the list add_planets_to_vicinity(systems_in_vicinity, num_planets_to_add) # as we've sorted the home system list before, lets shuffle it to ensure random order and return random.shuffle(home_systems) return home_systems