Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
def generate_monsters(monster_freq, systems):
    """
    Adds space monsters to systems.
    """

    # first, calculate the basic chance for monster generation in a system
    # based on the monster frequency that has been passed
    # get the corresponding value for the specified monster frequency from the universe tables
    inverse_monster_chance = fo.monster_frequency(monster_freq)
    # as the value in the universe table is higher for a lower frequency, we have to invert it
    # exception: a value of 0 means no monsters, in this case return immediately
    if inverse_monster_chance <= 0:
        return
    basic_chance = 1.0 / float(inverse_monster_chance)
    print "Default monster spawn chance:", basic_chance
    expectation_tally = 0.0
    actual_tally = 0

    # get all monster fleets that have a spawn rate and limit both > 0 and at least one monster ship design in it
    # (a monster fleet with no monsters in it is pointless) and store them with a spawn counter in a dict
    # this counter will be set to the spawn limit initially and decreased every time the monster fleet is spawned
    fleet_plans = {fp: fp.spawn_limit() for fp in fo.load_monster_fleet_plan_list("space_monster_spawn_fleets.txt")
                   if fp.spawn_rate() > 0.0 and fp.spawn_limit() > 0 and fp.ship_designs()}

    # map nests to monsters for ease of reporting
    nest_name_map = dict(zip(["KRAKEN_NEST_SPECIAL", "SNOWFLAKE_NEST_SPECIAL", "JUGGERNAUT_NEST_SPECIAL"], ["SM_KRAKEN_1", "SM_SNOWFLAKE_1", "SM_JUGGERNAUT_1"]))
    tracked_plan_tries = {name: 0 for name in nest_name_map.values()}
    tracked_plan_counts = {name: 0 for name in nest_name_map.values()}
    tracked_plan_valid_locations = {fp: 0 for fp, limit in fleet_plans.iteritems() if fp.name() in tracked_plan_counts}
    tracked_nest_valid_locations = {nest: 0 for nest in nest_name_map}

    if not fleet_plans:
        return

    # dump a list of all monster fleets meeting these conditions and their properties to the log
    print "Monster fleets available for generation at game start:"
    for fleet_plan in fleet_plans:
        print "...", fleet_plan.name(), ": spawn rate", fleet_plan.spawn_rate(),\
            "/ spawn limit", fleet_plan.spawn_limit(),\
            "/ effective chance", basic_chance * fleet_plan.spawn_rate(),\
            "/ can be spawned at", len([s for s in systems if fleet_plan.location(s)]), "systems"
        if fleet_plan.name() in nest_name_map.values():
            statistics.tracked_monsters_chance[fleet_plan.name()] = basic_chance * fleet_plan.spawn_rate()

    # for each system in the list that has been passed to this function, find a monster fleet that can be spawned at
    # the system and which hasn't already been added too many times, then attempt to add that monster fleet by
    # testing the spawn rate chance
    for system in systems:
        # collect info for tracked monster nest valid locations
        for planet in fo.sys_get_planets(system):
            for nest in tracked_nest_valid_locations:
                #print "\t tracked monster check planet: %d size: %s for nest: %20s  | result: %s" % (planet, fo.planet_get_size(planet), nest, fo.special_location(nest, planet))
                if fo.special_location(nest, planet):
                    tracked_nest_valid_locations[nest] += 1

        # collect info for tracked monster valid locations
        for fp in tracked_plan_valid_locations:
            if fp.location(system):
                tracked_plan_valid_locations[fp] += 1

        # filter out all monster fleets whose location condition allows this system and whose counter hasn't reached 0
        suitable_fleet_plans = [fp for fp, counter in fleet_plans.iteritems() if counter and fp.location(system)]
        # if there are no suitable monster fleets for this system, continue with the next
        if not suitable_fleet_plans:
            continue

        # randomly select one monster fleet out of the suitable ones and then test if we want to add it to this system
        # by making a roll against the basic chance multiplied by the spawn rate of this monster fleet
        expectation_tally += basic_chance * sum([fp.spawn_rate() for fp in suitable_fleet_plans]) / len(suitable_fleet_plans)
        fleet_plan = random.choice(suitable_fleet_plans)
        if fleet_plan.name() in tracked_plan_tries:
            tracked_plan_tries[fleet_plan.name()] += 1
        if random.random() > basic_chance * fleet_plan.spawn_rate():
            print "\t\t At system %4d rejected monster fleet %s from %d suitable fleets" % (system, fleet_plan.name(), len(suitable_fleet_plans))
            # no, test failed, continue with the next system
            continue
        actual_tally += 1
        if fleet_plan.name() in tracked_plan_counts:
            tracked_plan_counts[fleet_plan.name()] += 1

        # all prerequisites and the test have been met, now spawn this monster fleet in this system
        print "Spawn", fleet_plan.name(), "at", fo.get_name(system)
        # decrement counter for this monster fleet
        fleet_plans[fleet_plan] -= 1
        # create monster fleet
        monster_fleet = fo.create_monster_fleet(system)
        # if fleet creation fails, report an error and try to continue with next system
        if monster_fleet == fo.invalid_object():
            util.report_error("Python generate_monsters: unable to create new monster fleet %s" % fleet_plan.name())
            continue
        # add monsters to fleet
        for design in fleet_plan.ship_designs():
            # create monster, if creation fails, report an error and try to continue with the next design
            if fo.create_monster(design, monster_fleet) == fo.invalid_object():
                util.report_error("Python generate_monsters: unable to create monster %s" % design)

    print "Actual # monster fleets placed: %d; Total Placement Expectation: %.1f" % (actual_tally, expectation_tally)
    # finally, compile some statistics to be dumped to the log later
    statistics.monsters_summary = [(fp.name(), fp.spawn_limit() - counter) for fp, counter in fleet_plans.iteritems()]
    statistics.tracked_monsters_tries.update(tracked_plan_tries)
    statistics.tracked_monsters_summary.update(tracked_plan_counts)
    statistics.tracked_monsters_location_summary.update([(fp.name(), count) for fp, count in tracked_plan_valid_locations.iteritems()])
    statistics.tracked_nest_location_summary.update([(nest_name_map[nest], count) for nest, count in tracked_nest_valid_locations.items()])
Ejemplo n.º 4
0
def setup_empire(empire, empire_name, home_system, starting_species, player_name):
    """
    Sets up various aspects of an empire, like empire name, homeworld, etc.
    """

    # set empire name, if no one is given, pick one randomly
    if not empire_name:
        print "No empire name set for player", player_name, ", picking one randomly"
        empire_name = next(empire_name_generator)
    fo.empire_set_name(empire, empire_name)
    print "Empire name for player", player_name, "is", empire_name

    # check starting species, if no one is given, pick one randomly
    if not starting_species:
        print "No starting species set for player", player_name, ", picking one randomly"
        starting_species = next(starting_species_pool)
    print "Starting species for player", player_name, "is", starting_species
    statistics.empire_species[starting_species] += 1

    # pick a planet from the specified home system as homeworld
    planet_list = fo.sys_get_planets(home_system)
    # if the system is empty, report an error and return false, indicating failure
    if not planet_list:
        util.report_error("Python setup_empire: got home system with no planets")
        return False
    homeworld = random.choice(planet_list)

    # set selected planet as empire homeworld with selected starting species
    fo.empire_set_homeworld(empire, homeworld, starting_species)

    # set homeworld focus
    # check if the preferred focus for the starting species is among
    # the foci available on the homeworld planet
    available_foci = fo.planet_available_foci(homeworld)
    preferred_focus = fo.species_preferred_focus(starting_species)
    if preferred_focus in available_foci:
        # if yes, set the homeworld focus to the preferred focus
        print "Player", player_name, ": setting preferred focus", preferred_focus, "on homeworld"
        fo.planet_set_focus(homeworld, preferred_focus)
    elif len(available_foci) > 0:
        # if no, and there is at least one available focus,
        # just take the first of the list
        if preferred_focus == "":
            print "Player", player_name, ": starting species", starting_species, "has no preferred focus, using",\
                  available_foci[0], "instead"
        else:
            print "Player", player_name, ": preferred focus", preferred_focus, "for starting species",\
                  starting_species, "not available on homeworld, using", available_foci[0], "instead"
        fo.planet_set_focus(homeworld, available_foci[0])
    else:
        # if no focus is available on the homeworld, don't set any focus
        print "Player", player_name, ": no available foci on homeworld for starting species", starting_species

    # give homeworld starting buildings
    # use the list provided in starting_buildings.txt
    print "Player", player_name, ": add starting buildings to homeworld"
    for building in util.load_string_list("../starting_buildings.txt"):
        fo.create_building(building, homeworld, empire)

    # unlock starting techs, buildings, hulls, ship parts, etc.
    # use content file preunlocked_items.txt
    print "Player", player_name, ": add unlocked items"
    for item in fo.load_item_spec_list("preunlocked_items.txt"):
        fo.empire_unlock_item(empire, item.type, item.name)

    # add premade ship designs to empire
    print "Player", player_name, ": add premade ship designs"
    for ship_design in fo.design_get_premade_list():
        fo.empire_add_ship_design(empire, ship_design)

    # add starting fleets to empire
    # use content file starting_fleets.txt
    print "Player", player_name, ": add starting fleets"
    fleet_plans = fo.load_fleet_plan_list("starting_fleets.txt")
    for fleet_plan in fleet_plans:
        # first, create the fleet
        fleet = fo.create_fleet(fleet_plan.name(), home_system, empire)
        # if the fleet couldn't be created, report an error and try to continue with the next fleet plan
        if fleet == fo.invalid_object():
            util.report_error("Python setup empire: couldn't create fleet %s" % fleet_plan.name())
            continue
        # second, iterate over the list of ship design names in the fleet plan
        for ship_design in fleet_plan.ship_designs():
            # create a ship in the fleet
            # if the ship couldn't be created, report an error and try to continue with the next ship design
            if fo.create_ship("", ship_design, starting_species, fleet) == fo.invalid_object():
                util.report_error("Python setup empire: couldn't create ship %s for fleet %s"
                                  % (ship_design, fleet_plan.name()))
    return True