Пример #1
0
def execute_turn_events():
    print "Executing turn events for turn", fo.current_turn()

    # creating fields
    systems = fo.get_systems()
    radius = fo.get_universe_width() / 2.0
    if random() < max(0.0003 * radius, 0.03):
        if random() < 0.4:
            field_type = "FLD_MOLECULAR_CLOUD"
            size = 5.0
        else:
            field_type = "FLD_ION_STORM"
            size = 5.0

        x = y = radius
        dist_from_center = 0.0
        while (dist_from_center < radius) or any(hypot(fo.get_x(s) - x, fo.get_y(s) - y) < 50.0 for s in systems):
            angle = random() * 2.0 * pi
            dist_from_center = radius + uniform(min(max(radius * 0.02, 10), 50.0), min(max(radius * 0.05, 20), 100.0))
            x = radius + (dist_from_center * sin(angle))
            y = radius + (dist_from_center * cos(angle))

        print "...creating new", field_type, "field, at distance", dist_from_center, "from center"
        if fo.create_field(field_type, x, y, size) == fo.invalid_object():
            print >> sys.stderr, "Turn events: couldn't create new field"

    # creating monsters
    gsd = fo.get_galaxy_setup_data()
    monster_freq = MONSTER_FREQUENCY[gsd.monsterFrequency]
    # monster freq ranges from 30 (= one monster per 30 systems) to 3 (= one monster per 3 systems)
    # (example: low monsters and 150 Systems results in 150 / 30 * 0.001 = 0.005)
    if monster_freq > 0 and random() < len(systems) / monster_freq * 0.001:
        #only spawn Krill at the moment, other monsters can follow in the future
        if random() < 1:
            monster_type = "SM_KRILL_1"
        else:
            monster_type = "SM_FLOATER"

        # search for systems without planets or fleets
        candidates = [s for s in systems if len(fo.sys_get_planets(s)) <= 0 and len(fo.sys_get_fleets(s)) <= 0]
        if not candidates:
            print >> sys.stderr, "Turn events: unable to find system for monster spawn"
        else:
            system = choice(candidates)
            print "...creating new", monster_type, "at", fo.get_name(system)

            # create monster fleet
            monster_fleet = fo.create_monster_fleet(system)
            # if fleet creation fails, report an error
            if monster_fleet == fo.invalid_object():
                print >> sys.stderr, "Turn events: unable to create new monster fleet"
            else:
                # create monster, if creation fails, report an error
                monster = fo.create_monster(monster_type, monster_fleet)
                if monster == fo.invalid_object():
                    print >> sys.stderr, "Turn events: unable to create monster in fleet"

    return True
Пример #2
0
def log_monsters_summary():
    print "Space Monsters Placement Summary"
    for monster, counter in monsters_summary:
        if counter > 0:
            print "Placed space monster", monster, counter, "times"
    print
    inverse_monster_chance = fo.monster_frequency(fo.get_galaxy_setup_data().monsterFrequency)
    monster_chance = 1.0 / (1e-5 + inverse_monster_chance)
    # the following loop depends on name mapping done in monsters.py
    print "Tracked Monster and Nest Summary (base monster freq: %4.1f%%)" % (100 * monster_chance)
    print "%-18s | %8s | %8s | %8s | %12s | %s" %\
          ("Monster", "chance", "# tried", "# placed", "# valid sys locs", "# valid nest planet locs")
    for monster in tracked_monsters_summary:
        print "%-18s |  %5.2f   |   %4d   |   %4d   |       %4d       | %4d" % (monster, tracked_monsters_chance[monster],
            tracked_monsters_tries[monster], tracked_monsters_summary[monster],
            tracked_monsters_location_summary[monster], tracked_nest_location_summary[monster])
Пример #3
0
def log_species_summary():
    num_empires = sum(empire_species.values())
    num_species = len(fo.get_playable_species())
    exp_count = num_empires // num_species
    print "Empire Starting Species Summary for %d Empires and %d playable species" % (num_empires, num_species)
    print "Approximately %d to %d empires expected per species" % (max(0, exp_count - 1), exp_count + 1)
    print "%-16s :   # --     %%" % ("species")
    for species, count in empire_species.items():
        if count:
            print "%-16s : %3d -- %5.1f%%" % (species, count, 100.0 * count / num_empires)
    print
    inverse_native_chance = fo.native_frequency(fo.get_galaxy_setup_data().nativeFrequency)
    native_chance = 1.0 / (1e-5 + inverse_native_chance)
    print "Natives Placement Summary (native frequency: %.1f%%)" % (inverse_native_chance and (100 * native_chance))
    # 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 natives, in this case return immediately
    if inverse_native_chance <= 0:
        return
    native_potential_planet_total = sum(potential_native_planet_summary.values())
    for species in species_summary:
        if species_summary[species] > 0:
            settleable_planets = 0
            expectation_tally = 0.0
            for p_type in natives.planet_types_for_natives[species]:
                settleable_planets += potential_native_planet_summary[p_type]
                expectation_tally += native_chance * 100.0 * potential_native_planet_summary[p_type] / (1E-10 + len(natives.natives_for_planet_type[p_type]))
            expectation = expectation_tally / (1E-10 + settleable_planets)
            print "Settled natives %18s on %3d planets -- %5.1f%% of total and %5.1f%% vs %5.1f%% (actual vs expected) of %s planets" % \
                (species, species_summary[species], 100.0 * species_summary[species] / (1E-10 + native_potential_planet_total),
                 100.0 * species_summary[species] / (1E-10 + settleable_planets), expectation, [str(p_t) for p_t in natives.planet_types_for_natives[species]])
    print
    native_settled_planet_total = sum(settled_native_planet_summary.values())
    print "Planet Type Summary for Native Planets (native frequency: %.1f%%)" % (inverse_native_chance and (100 * native_chance))
    print "%19s : %-s" % ("Potential (% of tot)", "Settled (% of potential)")
    print "%-13s %5d : %5d" % ("Totals", native_potential_planet_total, native_settled_planet_total)
    for planet_type, planet_count in potential_native_planet_summary.items():
        settled_planet_count = settled_native_planet_summary.get(planet_type, 0)
        potential_percent = 100.0 * planet_count / (1E-10 + native_potential_planet_total)
        settled_percent = 100.0 * settled_planet_count / (1E-10 + planet_count)
        print "%-12s %5.1f%% : %5.1f%%" % (planet_type.name, potential_percent, settled_percent)
def inspect_universe_generation_interface(*args, **kwargs):
    import freeorion as fo
    tech = fo.getTech('LRN_ARTIF_MINDS')
    universe = fo.get_universe()
    empire = fo.get_empire(1)
    rules = fo.getGameRules()
    hull_type = fo.getHullType('SH_XENTRONIUM')
    species = fo.getSpecies('SP_ABADDONI')
    inspect(
        fo,
        instances=[
            fo.getFieldType('FLD_ION_STORM'),
            fo.getBuildingType('BLD_SHIPYARD_BASE'),
            hull_type,
            hull_type.slots,
            fo.getPartType('SR_WEAPON_1_1'),
            fo.getSpecial('MODERATE_TECH_NATIVES_SPECIAL'),
            species,
            fo.diplomaticMessage(1, 2, fo.diplomaticMessageType.acceptPeaceProposal),
            rules,
            tech,
            tech.unlockedItems,
            rules.getRulesAsStrings,
            universe,
            universe.effectAccounting,
            universe.buildingIDs,
            fo.get_galaxy_setup_data(),
            empire,
            empire.colour,
            empire.productionQueue,
            empire.researchQueue,
        ],
        classes_to_ignore=(
            'IntBoolMap', 'IntDblMap', 'IntFltMap', 'IntIntMap', 'IntPairVec', 'IntSetSet',
            'MeterTypeAccountingInfoVecMap', 'MeterTypeMeterMap', 'MeterTypeStringPair', 'MonsterFleetPlan',
            'PairIntInt_IntMap', 'RuleValueStringStringPair', 'ShipPartMeterMap', 'VisibilityIntMap',
            'AccountingInfoVec', 'IntSet', 'StringSet', 'StringVec',
        ),
        path=".",
    )
Пример #5
0
def inspect_universe_generation():
    """
    Inspect function for universe generation interface.

    We have no way to run it without modifying of game code.

    To generate interface
    put call before return section of universe_generation.universe_generator.create_universe function
    """
    import freeorion as fo
    techs = fo.techs()
    universe = fo.get_universe()
    planet_ids = universe.planetIDs

    system_ids = universe.systemIDs
    system = universe.getSystem(system_ids[0])

    building_ids = universe.buildingIDs
    building = universe.getBuilding(building_ids[0])
    empire_ids = fo.get_all_empires()
    empire = fo.get_empire(empire_ids[0])
    fields_ids = universe.fieldIDs
    field = universe.getField(fields_ids[0])

    fleets_ids = universe.fleetIDs
    fleet = universe.getFleet(fleets_ids[0])
    tech = fo.getTech(techs[0])
    unlocked_items = tech.unlockedItems

    ship = universe.getShip(list(fleet.shipIDs)[0])
    # meter = ship.getMeter(fo.meterType.maxFuel)

    design = ship.design

    universe_object = universe.getObject(universe.systemIDs[0])

    # fo.getHullType ?

    species = None
    special = None
    planets = [universe.getPlanet(pid) for pid in planet_ids]
    for planet in planets:
        species_name = planet.speciesName
        if species_name:
            species = fo.getSpecies(species_name)
        specials = list(planet.specials)
        if specials:
            special = fo.getSpecial(specials[0])

    inspect(
        fo,
        instances=[
            fo.get_galaxy_setup_data(),
            universe,
            planet_ids,
            universe.getPlanet(planet_ids[0]),
            system,
            techs,
            tech,
            tech.unlockedTechs,
            building,
            fo.getBuildingType(building.buildingTypeName),
            empire,
            field,
            fo.getFieldType(field.fieldTypeName),
            fleet,
            ship,
            # meter,
            design,
            fleet.shipIDs,  # int set wtf?
            universe_object,
            system.starlanesWormholes,
            empire.systemSupplyRanges,
            empire.supplyProjections(),
            empire.obstructedStarlanes(),
            empire.planetsWithWastedPP,
            unlocked_items,
            species,
            special
        ],
        classes_to_ignore=(
            'FleetPlan', 'GGColor', 'MonsterFleetPlan', 'PlayerSetupData', 'ShipPartMeterMap', 'ShipSlotVec',
            'VisibilityIntMap', 'diplomaticMessage', 'diplomaticStatusUpdate', 'meter',
        ),
        path=''
    )
    # fo.sys_get_star_type(system),
    # fo.planet_get_size(pid),
    # fo.planet_get_type(planet),
    # fo.species_get_planet_environment(species, planet_type),
    # fo.species_preferred_focus(species),

    # fo.getBuildingType(string)
    # fo.getFieldType(string)
    # fo.getHullType(string)
    # fo.getPartType(string)
    # fo.getShipDesign(number)
    # fo.getSpecial(string)
    # fo.getSpecies(string)
    # fo.getTech(string)
    # fo.getTechCategories(obj)
    # fo.get_empire(number)
    # fo.planet_get_species(number)
    # fo.techsInCategory(string)
    exit(1)
Пример #6
0
def create_universe(psd_map):
    """
    Main universe generation function invoked from C++ code.
    """
    print "Python Universe Generator"

    # fetch universe and player setup data
    gsd = fo.get_galaxy_setup_data()
    total_players = len(psd_map)

    # initialize RNG
    seed_rng(gsd.seed)
    seed_pool = [random.random() for _ in range(100)]

    # 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)
    size = max(gsd.size, (total_players * 3))
    if size > gsd.size:
        # gsd.size = 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" % (size, total_players)

    # calculate star system positions
    seed_rng(seed_pool.pop())
    system_positions = calc_star_system_positions(gsd.shape, size)
    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(gsd.starlaneFrequency)
    print "Starlanes generated"

    print "Compile list of home systems..."
    seed_rng(seed_pool.pop())
    home_systems = compile_home_system_list(total_players, systems)
    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 Natives"
    seed_rng(seed_pool.pop())
    generate_natives(gsd.nativeFrequency, systems, home_systems)

    print "Generating Space Monsters"
    seed_rng(seed_pool.pop())
    generate_monsters(gsd.monsterFrequency, systems)

    print "Distributing Starting Specials"
    seed_rng(seed_pool.pop())
    distribute_specials(gsd.specialsFrequency, 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()
    print "############################################################"
    statistics.log_monsters_summary()
    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
Пример #7
0
def add_planets_to_vicinity(vicinity, num_planets):
    """
    Adds the specified number of planets to the specified systems.
    """
    print "Adding", num_planets, "planets to the following systems:", vicinity
    gsd = fo.get_galaxy_setup_data()  # get galaxy setup data, we will need that later

    # 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
            while star_type not in star_types_real:
                star_type = pick_star_type(gsd.age)

        # 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
Пример #8
0
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())
    gsd.dump()
    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())

    # set game uid
    empire_names = []
    for psd in psd_map.values():
        empire_names.append(psd.empire_name)

    empire_names.sort()
    for i, v in enumerate(empire_names):
        empire_names[i] = v.capitalize()[:2]

    fo.get_galaxy_setup_data().gameUID = "".join(empire_names) + str(random.randint(0, 999)).zfill(3)

    print "Game UID %s" % fo.get_galaxy_setup_data().gameUID

    # finally, write some statistics to the log file
    print "############################################################"
    print "##             Universe generation statistics             ##"
    print "############################################################"
    universe_statistics.log_planet_count_dist(systems)
    print "############################################################"
    universe_statistics.log_planet_type_summary(systems)
    print "############################################################"
    universe_statistics.log_species_summary(gsd.native_frequency)
    print "############################################################"
    universe_statistics.log_monsters_summary(gsd.monster_frequency)
    print "############################################################"
    universe_statistics.log_specials_summary()
    print "############################################################"
    universe_statistics.log_systems()
    universe_statistics.log_planets()

    if error_list:
        print "Python Universe Generator completed with errors"
        return False
    else:
        print "Python Universe Generator completed successfully"
        return True