Beispiel #1
0
def has_min_planets_in_vicinity(system):
    """
    Checks if the specified system has a certain minimum of planets in the near vicinity.
    The near vicinity are all systems within HS_VICINITY_RANGE jumps of the system.
    """
    systems_in_vicinity = get_systems_within_jumps(system, HS_VICINITY_RANGE)
    return count_planets_in_systems(systems_in_vicinity) > min_planets_in_vicinity_limit(len(systems_in_vicinity))
Beispiel #2
0
def has_min_planets_in_vicinity(system):
    """
    Checks if the specified system has a certain minimum of planets in the near vicinity.
    The near vicinity are all systems within HS_VICINITY_RANGE jumps of the system.
    """
    systems_in_vicinity = get_systems_within_jumps(system, HS_VICINITY_RANGE)
    return count_planets_in_systems(
        systems_in_vicinity) > min_planets_in_vicinity_limit(
            len(systems_in_vicinity))
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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