From: <dil...@us...> - 2014-08-19 22:53:06
|
Revision: 7515 http://sourceforge.net/p/freeorion/code/7515 Author: dilvish-fo Date: 2014-08-19 22:52:58 +0000 (Tue, 19 Aug 2014) Log Message: ----------- lowered odds of multiple specials on same object, and added reporting re such, and also additional reporting of monster spawns and planet size distribution Modified Paths: -------------- trunk/FreeOrion/default/universe_generation/monsters.py trunk/FreeOrion/default/universe_generation/specials.py trunk/FreeOrion/default/universe_generation/statistics.py Modified: trunk/FreeOrion/default/universe_generation/monsters.py =================================================================== --- trunk/FreeOrion/default/universe_generation/monsters.py 2014-08-19 22:51:27 UTC (rev 7514) +++ trunk/FreeOrion/default/universe_generation/monsters.py 2014-08-19 22:52:58 UTC (rev 7515) @@ -19,12 +19,19 @@ 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_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 @@ -37,6 +44,15 @@ # 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: + 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 @@ -45,10 +61,15 @@ # 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 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) @@ -59,12 +80,16 @@ # 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 + continuetracked_monsters_location_summary # 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_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_sumary.update([(nest_name_map[nest], count) for nest, count in tracked_nest_valid_locations.items()]) \ No newline at end of file Modified: trunk/FreeOrion/default/universe_generation/specials.py =================================================================== --- trunk/FreeOrion/default/universe_generation/specials.py 2014-08-19 22:51:27 UTC (rev 7514) +++ trunk/FreeOrion/default/universe_generation/specials.py 2014-08-19 22:52:58 UTC (rev 7515) @@ -29,10 +29,12 @@ # attempt to apply a special to each universe object in the list that has been passed to this function # by finding a special that can be applied to it and hasn't been added too many times, and then attempt # to add that special by testing its spawn rate + repeat_rate = {1 : 0.08, 2 : 0.05, 3 : 0.01, 4 : 0.00} for univ_obj in universe_objects: # for this universe object, find a suitable special # start by shuffling our specials list, so each time the specials are considered in a new random order random.shuffle(specials) + num_here = 0 # then, consider each special until one has been found or we run out of specials # (the latter case means that no special is added to this universe object) @@ -54,7 +56,9 @@ # the basic probability multiplied by the spawn rate of the special if random.random() > basic_chance * fo.special_spawn_rate(special): # no, test failed, break out of the specials loop and continue with the next universe object + statistics.specials_repeat_dist[num_here] += 1 break + num_here += 1 # all prerequisites and the test have been met, now add this special to this universe object fo.add_special(univ_obj, special) @@ -64,6 +68,9 @@ print "Special", special, "added to", fo.get_name(univ_obj) # stop attempting to add specials here? give a small chance to try more than one special - if random.random() > 0.08: + if random.random() > repeat_rate.get(num_here, 0.0): # sorry, no, break out of the specials loop and continue with the next universe object - break \ No newline at end of file + statistics.specials_repeat_dist[num_here] += 1 + break + else: + statistics.specials_repeat_dist[num_here] += 1 Modified: trunk/FreeOrion/default/universe_generation/statistics.py =================================================================== --- trunk/FreeOrion/default/universe_generation/statistics.py 2014-08-19 22:51:27 UTC (rev 7514) +++ trunk/FreeOrion/default/universe_generation/statistics.py 2014-08-19 22:52:58 UTC (rev 7515) @@ -8,20 +8,31 @@ potential_native_planet_summary = {planet_type: 0 for planet_type in planets.planet_types} settled_native_planet_summary = {planet_type: 0 for planet_type in planets.planet_types} monsters_summary = [] +tracked_monsters_summary = {} +tracked_monsters_location_summary = {} +tracked_nest_location_sumary = {} specials_summary = {special: 0 for special in fo.get_all_specials()} +specials_repeat_dist = {count: 0 for count in [0, 1, 2, 3, 4]} - def log_planet_count_dist(sys_list): planet_count_dist = {} + planet_size_dist = {size : 0 for size in planets.planet_sizes} for system in sys_list: planet_count = 0 for planet in fo.sys_get_planets(system): - if fo.planet_get_size(planet) in planets.planet_sizes: + this_size = fo.planet_get_size(planet) + if this_size in planets.planet_sizes: planet_count += 1 + planet_size_dist[this_size] += 1 planet_count_dist.setdefault(planet_count, [0])[0] += 1 - print "Planet Count Distribution: planets_in_system | num_systems" + planet_tally = sum(planet_size_dist.values()) + print "Planet Count Distribution: planets_in_system | num_systems | % of systems" for planet_count, sys_count in planet_count_dist.items(): - print "\t\t\t%2d | %5d" % (planet_count, sys_count[0]) + print "\t\t\t%2d | %5d | %4.1f%%" % (planet_count, sys_count[0], 100.0 * sys_count[0] / len(sys_list)) + print + print "Planet Size Distribution: size | count | % of planets" + for planet_size, planet_count in planet_size_dist.items(): + print "\t\t%-12s | %5d | %4.1f%%" % (planet_size, planet_count, 100.0 * planet_count / planet_tally) def log_planet_type_summary(sys_list): @@ -32,7 +43,7 @@ planet_total = sum(planet_type_summary.values()) print "Planet Type Summary for a total of %d placed planets" % planet_total for planet_type, planet_count in planet_type_summary.items(): - print "%-12s %.1f%%" % (planet_type.name, 100.0 * planet_count / planet_total) + print "%-12s %4.1f%%" % (planet_type.name, 100.0 * planet_count / planet_total) def log_species_summary(): @@ -81,10 +92,24 @@ 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 | %12s | %s" % ("Monster", "# placed", "# valid sys locs", "# valid nest planet locs") + for monster in tracked_monsters_summary: + print "%-18s | %4d | %4d | %4d" % (monster, tracked_monsters_summary[monster], + tracked_monsters_location_summary[monster], tracked_nest_location_sumary[monster]) - def log_specials_summary(): print "Special Placement Summary" for special in specials_summary: if specials_summary[special] > 0: print "Placed special", special, specials_summary[special], "times" + print + print "Specials Count(Repeat) Distribution:" + print "\t count | tally | % of objects" + objects_tally = sum(specials_repeat_dist.values()) + for number, tally in specials_repeat_dist.items(): + print "\t\t%3d | %5d | %4.1f%%" % (number, tally, 100.0 * tally / objects_tally) |