def execute_buys(w, city_dict): # city_dict = w.live_cities() for city_id, the_city in cli_f.progressbar(city_dict.items(), "Executing buys: ", 60, True): # for city_id, the_city in city_dict.items(): for s in the_city.sells: s.execute()
def check_operative_locations(cursor, verbose): """Finds operatives in dead cities and relocates them""" teams_dict = team_q.get_all_teams(cursor) operatives_dict = operative_q.get_all_operatives(cursor) city_dict = city_q.get_all_cities(cursor) # Get a list of the dead cities dead_city_list = [] for c_id, the_city in city_dict.items(): if the_city.dead > 0 or not teams_dict[the_city.team].active: dead_city_list.append(str(c_id)) # Find operatives in those cities query = """SELECT id FROM operatives WHERE city in (%s) and died < 1""" % ",".join(dead_city_list) try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) move_op_list = {} for row in cursor: o = row['id'] t = operatives_dict[o].team if not teams_dict[t].active: continue if t not in move_op_list: move_op_list[t] = [] move_op_list[t].append(str(o)) # Find out which teams we need to get a city for teams_cities = {} for t in move_op_list.keys(): teams_cities[t] = -1 # Find cities for those teams if verbose: it = cli_f.progressbar(city_dict.items(), "ops_check.check_operative_locations: ", 40, with_eta = True) else: it = city_dict.items() for c_id, the_city in it: if the_city.team in teams_cities and not teams_dict[the_city.team].dead: teams_cities[the_city.team] = c_id # Now run the queries queries = [] for t, c in teams_cities.items(): query = "UPDATE operatives SET city = %d, arrival = %d WHERE id in (%s)" % ( c, common.current_turn(), ",".join(move_op_list[t]), ) try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query))
def execute_buys(w, city_dict, verbose=True): # city_dict = w.live_cities() if verbose: it = cli_f.progressbar(city_dict.items(), "Executing buys: ", 60, True) else: it = city_dict.items() for city_id, the_city in it: for s in the_city.sells: _execute(w, city_dict, s)
def build_unit_equipment_strings(cursor, verbose): # Does what it says on the tin the_world = world.World(cursor) # the_world.units() unit_dict = unit_q.get_all_live_units(cursor) if verbose: it = cli_f.progressbar(unit_dict.items(), "military_check.build_unit_equipment_strings: ", 40, with_eta = True) else: it = unit_dict.items() for unit_id, the_unit in it: unit_f.rebuild_equipment_string(cursor, unit_id, the_world)
def get_happiness(cursor, verbose): w = world.World(cursor) if verbose: it = cli_f.progressbar(w.live_cities().items(), "cities_check.get_happiness: ", 40, with_eta = True) else: it = w.live_cities().items() queries = [] for city_id, the_city in it: queries.append("UPDATE cities SET happiness = %d WHERE id = %d;" % (city_rules.get_happiness(w, the_city), city_id)) database.query(cursor, *queries)
def train(self): self.current_inputs = self.inputs try: for c in cli_f.progressbar(range(0, self.cycles), prefix = "", size = 60, with_eta=True): # for c in range(0, self.cycles): self._cycle() except KeyboardInterrupt as e: # Flush progress bar print(" ".join([" " for x in range(0,40)])) print("Exiting due to keyboard interrupt:") except Exception as e: raise finally: self.end()
def city_wealth(cursor, verbose): queries = [] w = world.World(database.get_cursor()) city_f.apply_city_matrix(w, compress=False) if verbose: it = cli_f.progressbar(w.live_cities().items(), "cities_check.city_wealth: ", 40, with_eta = True) else: it = w.live_cities().items() for k, c in it: c.wealth = city_rules.wealth_rate(w, c) queries.append("UPDATE cities SET wealth = %d WHERE id = %d;" % (c.wealth, k)) database.query(cursor, *queries)
def city_terrain(cursor, verbose): queries = [] city_dict = city_q.get_live_cities(cursor) if verbose: it = cli_f.progressbar(city_dict.items(), "cities_check.city_terrain: ", 40, with_eta = True) else: it = city_dict.items() for k, c in it: t = mapper_q.get_terrain(cursor, c.x, c.y) if t != c.terrain: queries.append("UPDATE cities SET terrain = %d WHERE id = %d;" % (t, k)) database.query(cursor, *queries)
def overlapping_cities(cursor, verbose): city_dict = city_q.get_live_cities(cursor) checked = [] overlap_dict = {} for id1, c1 in city_dict.items(): c1.overlap = 0 # Cache some stuff if verbose: it = cli_f.progressbar(city_dict.items(), "cities_check.overlapping_cities: ", 40, with_eta = True) else: it = city_dict.items() for id1, c1 in it: checked.append(id1) for id2, c2 in city_dict.items(): if id2 in checked: continue amount = city_f.overlap(c1, c2) c1.overlap += city_f.overlap_percentage(c1, amount) c2.overlap += city_f.overlap_percentage(c2, amount) # Reset all cities query = """UPDATE cities SET overlap = 0""" try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) updates = 0 for id1, c1 in city_dict.items(): if c1.overlap >= 1: updates += 1 query = "UPDATE cities SET overlap = %d WHERE id = %d;" % (c1.overlap, id1) # print("%s - %s" % (query, c1.name)) # continue try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query))
def build_supplies(cursor, verbose): city_dict = city_q.get_live_cities(cursor) city_supply_dict = {} for k, v in city_dict.items(): v.icon_size = map_data.map_image_size(v.population+v.slaves)/4 if verbose: it = cli_f.progressbar(map_resources.data_list, "cities_check.build_supplies: ", 40, with_eta = True) else: it = map_resources.data_list for r, x, y in it: this_city = (-1, 9999) for k, v in city_dict.items(): dist = path_f.pythagoras((v.x, v.y), (x, y)) if dist < v.icon_size: if this_city[1] > v.founded: this_city = (k, v.founded) if this_city[0] > 0: if this_city[0] not in city_supply_dict: city_supply_dict[this_city[0]] = [] city_supply_dict[this_city[0]].append(r) query = "UPDATE cities SET str_supplies = '';" try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) for k, v in city_supply_dict.items(): vset = [str(r) for r in set(v)] query = "UPDATE cities SET str_supplies = '{0}' WHERE id = {1:d};".format( ",".join(vset), k, ) try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query))
def check_for_garrisons(cursor, verbose): garrisons_made = 0 garrisons_named = 0 city_list = [] city_names = {} garrison_names = {} # Get cities query = "SELECT id, name FROM cities WHERE dead < 1" try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) for row in cursor: city_list.append(row['id']) city_names[row['id']] = row['name'] # Get garrisons query = "SELECT garrison, name FROM armies WHERE garrison > 0;" try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) for row in cursor: garrison_names[row['garrison']] = row['name'] if verbose: it = cli_f.progressbar(city_list, "military_check.check_for_garrisons: ", 40, with_eta = True) else: it = city_list for city_id in it: # row = cursor.fetchone() if city_id not in garrison_names: # No garrison exists for this city, best create one database.query(cursor, army_f.create_garrison(cursor, city_id)) garrisons_made += 1 else: # Has a garrison, lets check the name if garrison_names[city_id] != "%s garrison" % city_names[city_id]: database.query(cursor, army_f.name_garrison(city_id, city_names[city_id])) garrisons_named += 1
def find_buys(w, city_dict): # city_dict = w.live_cities() # End point stopper w.suppliers = {r: set() for r in sad_rules.res_list} for city_id, the_city in city_dict.items(): for r in sad_rules.res_list: if the_city.goods[r] > 0: w.suppliers[r].add(city_id) i = 0 # for city_id, the_city in city_dict.items(): for city_id, the_city in cli_f.progressbar(city_dict.items(), "Finding buys: ", 60, True): needs = the_city.current_demands() i += 1 # 20 = 115 # 100 = 622.5 # Full data at max hops 2 = # if i >= 10: return # For each supply we want for r in needs: prices = [] for c, d in the_city.connections.items(): if city_id in city_dict[c].connections: prices.append(request_price(w, city_dict, the_city, city_dict[c], r, current_path=[city_id])) # We want to filter out the best best = best_price(prices) if best != None: # We need to work out how much of this we can afford availiable = the_city.wealth / len(needs) best.set_amount(min(availiable / best.price, -the_city.goods[r])) the_city.buys.append(best) best.get_actual().sells.append(best)
def approve_buys(w, city_dict): # city_dict = w.live_cities() team_dict = w.teams() for city_id, the_city in cli_f.progressbar(city_dict.items(), "Approving buys: ", 60, True): # for city_id, the_city in city_dict.items(): accepted_sells = [] # We need to work out which sells we're gonna do # preferential treatment is given to those that we have a low tax rate to # it's possible we can honour more than one sell # the sells should all be for just a single supply # Temporary counters goods = sum([(a if a > 0 else 0) for r, a in the_city.goods.items()]) goods_dict = dict(the_city.goods) # Keep going while we can while goods > 0 and len(accepted_sells) < len(the_city.sells): favoured = (999999, None) for s in the_city.sells: if s in accepted_sells: continue if w.get_taxes(the_city.team, s.get_2nd_seller()) < favoured[0]: favoured = (w.get_taxes(the_city.team, s.buyer.team), s) # Actual amount needs to be limited accepted = favoured[1] accepted.set_amount(min(goods_dict[accepted.resource], accepted.amount)) accepted_sells.append(accepted) goods -= accepted.amount goods_dict[accepted.resource] -= accepted.amount the_city.sells = accepted_sells
def approve_buys(w, city_dict, verbose=True): team_dict = w.teams() if verbose: it = cli_f.progressbar(city_dict.items(), "Approving buys: ", 60, True) else: it = city_dict.items() sales_count = 0 sales_lowered = 0 for city_id, the_city in it: if len(the_city.sells) == 0: continue # print("\n\n") # print(the_city.sells) # exit() accepted_sells = [] marked_sells = [] # We need to work out which sells we're gonna do # preferential treatment is given to those that we have a low tax rate to # it's possible we can honour more than one sell # the sells should all be for just a single supply # If the sells are not for a single supply it will be an inefficent system as only 1 favoured is tracked # Temporary counters goods = sum([(a if a > 0 else 0) for r, a in the_city.goods.items()]) goods_dict = dict(the_city.goods) # Keep going while we can i = 0 while goods > 0 and len(accepted_sells) < len(the_city.sells): i += 1 if i > 100: break favoured = None favoured_tax = 9999 for i, s in enumerate(the_city.sells): if i in marked_sells: continue # s[1] is the path # 0 is us # 1 is the first buyer buyer = s[1][1] if w.tax_cache[(the_city.team, city_dict[buyer].team)] < favoured_tax: favoured_i = i favoured = s favoured_tax = w.tax_cache[(the_city.team, city_dict[buyer].team)] # print("Fav: %s, %s" % (favoured_tax, str(favoured))) # Actual amount needs to be limited # marked_sells.append(favoured) marked_sells.append(favoured_i) final_buyer = favoured[1][-1] r = favoured[0] sales_count += 1 if goods_dict[r] < favoured[2]: sales_lowered += 1 amount = min(goods_dict[r], favoured[2]) # print(amount, " ") # Move counters, add amount to the sell favoured = (favoured[0], favoured[1], amount) accepted_sells.append(favoured) goods -= amount goods_dict[r] -= amount # goods = -100 the_city.sells = accepted_sells # for s in the_city.sells: # print(s) # exit() print("Sale count: %s" % sales_count) print("Sales lowered: %s" % sales_lowered)
def find_buys(w, city_dict, verbose=True): # city_dict = w.live_cities() # End point stopper # w.suppliers = {r:set() for r in sad_rules.res_list} # for city_id, the_city in city_dict.items(): # the_city.best_price = {} # # for r in sad_rules.res_list: # if the_city.goods[r] > 0: # w.suppliers[r].add(city_id) for city_id, the_city in city_dict.items(): the_city.needs_cache = the_city.current_demands() if verbose: it = cli_f.progressbar(range(0, config['hops']+1), "Hopping: ", 60, True) else: it = range(0, config['hops']+1) for h in it: # for h in range(0, max_hops+1): # for city_id, the_city in cli_f.progressbar(city_dict.items(), "Hopping %d: " % h, 60, True): for city_id, the_city in city_dict.items(): _discover(w, city_dict, the_city, h) if verbose: it = cli_f.progressbar(city_dict.items(), "Finding buys: ", 60, True) else: it = city_dict.items() for city_id, the_city in it: if the_city.wealth <= 1: continue needs = the_city.current_demands() offers = [] current_best_price = {} for r in needs: current_best_price[r] = (9999, []) # For each supply we want for c, d in the_city.connections.items(): if city_id in city_dict[c].connections: for r in needs: if city_dict[c].best_price[config['hops']][r][0] > 1000: continue offers.append() # Price is made from price saved at other city times the get_price multiplier offer_price = get_price(w, the_city, city_dict[c]) * city_dict[c].best_price[config['hops']][r][0] if new_price < current_best_price[r][0]: availiable = the_city.wealth/len(needs) amount = min(availiable/new_price, -the_city.goods[r]) current_best_price[r] = (new_price, list(city_dict[c].best_price[config['hops']][r][1]) + [the_city.id], amount) # Now to turn them into Buys for r in needs: if current_best_price[r][0] > 1000: continue city_dict[current_best_price[r][1][0]].sells.append((r, current_best_price[r][1], current_best_price[r][2]))
def test_all(options): options.all = True tests(options) options.verbose = True the_world = spy_world.Spy_world(database.get_cursor()) cli_f.output_ti(options, the_world, skip_upload=True) cli_f.output_to(options, the_world, skip_upload=True) cli_f.output_stats(options, the_world, skip_upload=True) cli_f.output_map(options, the_world, skip_upload=True) cli_f.output_wh(options, the_world, skip_upload=True) cli_f.output_oh(options, the_world, skip_upload=True) cli_f.output_spyrep(options, the_world, skip_upload=True) cli_f.output_tmap(options, the_world, skip_upload=True) cli_f.output_json(options, skip_upload=True) funcs = ( the_world.relations, the_world.border_history, # the_world.prep_for_orders(self):, # the_world.prep_for_to(self):, # the_world.prep_for_stats(self):, # the_world.prep_for_oh(self):, # the_world.prep_for_ti(self):, # the_world.prep_for_start(self):, # the_world.building_requirements(self):, # the_world._lookup(self, name, lower=False, force_requery=False):, the_world.artefacts_lookup, the_world.armies_lookup, the_world.buildings_lookup, the_world.cities_lookup, the_world.campaigns_lookup, the_world.deities_lookup, the_world.equipment_lookup, the_world.evolutions_lookup, the_world.operatives_lookup, the_world.powers_lookup, the_world.spells_lookup, the_world.techs_lookup, the_world.teams_lookup, the_world.squads_lookup, the_world.units_lookup, the_world.wonders_lookup, # the_world._build_lookup_from_team(self, name, force_requery=False):, # the_world._lookup_all_from_team(self, name, force_requery=False):, # the_world._lookup_from_team(self, name, team_id, force_requery=False):, # the_world.armies_lookup_from_team(self, team_id, force_requery=False):, # the_world.units_lookup_from_team(self, team_id, force_requery=False):, # the_world._dict(self, name, force_requery=False):, the_world.armies, the_world.artefacts, the_world.buildings, the_world.cities, the_world.campaigns, the_world.deities, the_world.equipment, the_world.evolutions, the_world.kills, the_world.servants, the_world.operatives, the_world.powers, the_world.players, the_world.spells, the_world.techs, the_world.squads, the_world.teams, the_world.units, # the_world.json_ti(self, team, turn, force_requery=False), the_world.wonders, # the_world._build_from_team(self, name, force_requery=False):, # the_world._all_from_team(self, name, force_requery=False):, # the_world._from_team(self, name, team_id, force_requery=False):, # the_world.armies_from_team(self, team_id, force_requery=False):, # the_world.cities_from_team(self, team_id, force_requery=False):, # the_world.kills_from_turn(self, team_id, force_requery=False):, # the_world.kills_from_camp(self, team_id, force_requery=False):, # the_world.players_from_team(self, team_id, force_requery=False):, # the_world.operatives_from_team(self, team_id, force_requery=False):, # the_world.squads_from_team(self, team_id, force_requery=False):, # the_world.units_from_team(self, team_id, force_requery=False):, # the_world.squads_lookup_from_army(self, army_id, force_requery=False):, the_world.cities_with_wonders, the_world.cities_with_artefacts, the_world.active_teams, the_world.live_cities, # the_world.live_cities_from_team(self, team_id, force_requery=False):,, # armies_by_base(self, base, force_requery=False) # armies_in_area(self, area, radius=10, force_requery=False) # operatives_in_area(self, area, radius=10, force_requery=False) # operatives_in_city(self, city_id, force_requery=False) # cities_in_area(self, area, radius=10, force_requery=False) # race_difference(self, race_1, race_2) ) for f in cli_f.progressbar(funcs, "Testing world: ", 60, True): f()
def merge_squads(cursor, verbose): the_world = world.World(cursor) squad_dict = the_world.squads() army_dict = the_world.armies() teams_dict = the_world.teams() squad_by_army = {} for k, s in squad_dict.items(): if s.army not in squad_by_army: squad_by_army[s.army] = [] squad_by_army[s.army].append(s.id) # Get active teams active_teams = [] for team_id, the_team in teams_dict.items(): if the_team.ir or not the_team.active: continue active_teams.append(team_id) # Pairs will contain tuples of what we want to merge queries = [] if verbose: it = cli_f.progressbar(army_dict.items(), "military_check.merge_squads: ", 40, with_eta = True) else: it = army_dict.items() for army_id, the_army in it: if the_army.team not in active_teams: continue if army_id not in squad_by_army: continue skip_squads = [] # Outside loop looks at the squad we may want to merge for squad_id_1 in squad_by_army[army_id]: if squad_id_1 in skip_squads: continue the_squad_1 = squad_dict[squad_id_1] for squad_id_2 in squad_by_army[army_id]: if squad_id_1 == squad_id_2: continue if squad_id_2 in skip_squads: continue the_squad_2 = squad_dict[squad_id_2] if the_squad_1.unit == the_squad_2.unit: if the_squad_1.name == the_squad_2.name: skip_squads.append(squad_id_2) # Update size queries.append("UPDATE squads SET amount = %d WHERE id = %d;" % (the_squad_1.amount + the_squad_2.amount, squad_id_1)) # Delete 2nd squad queries.append("DELETE FROM squads WHERE id = %d" % squad_id_2) # print "\n".join(queries) cursor.execute("BEGIN") for query in queries: try: cursor.execute(query) except Exception as e: cursor.execute("ROLLBACK") raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) cursor.execute("COMMIT")
def check_unit_categories(cursor, verbose): queries = [] unit_dict = unit_q.get_all_live_units(cursor) equipment_dict = equipment_q.get_all_equipment(cursor) unit_q.mass_get_unit_equipment(cursor, unit_dict) # Default query = """UPDATE units SET crew = 1;""" try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) if verbose: it = cli_f.progressbar(unit_dict.items(), "military_check.check_unit_categories: ", 40, with_eta = True) else: it = unit_dict.items() for unit_id, the_unit in it: the_unit.transport = 0 the_unit.move_type = 0 the_unit.move_speed = 0 the_unit.crew = 1 the_unit.weapon_cat = 0 the_unit.armour_cat = 0 the_unit.move_cat = 0 the_unit.training_cat = 0 ranged = False melee = False # Loop through all it's equipment for e in the_unit.equipment: the_e = equipment_dict[e] if the_e.range > 2: ranged = True elif the_e.range == 0: melee = True the_unit.transport = max(the_e.transport, the_unit.transport) the_unit.crew = max(the_unit.crew, the_e.crew) # the_unit.move_type = 0 # the_unit.move_speed = 0 # the_unit.type_cat = 0 the_unit.armour_cat = max(the_unit.armour_cat, the_e.armour_cat) the_unit.move_cat = max(the_unit.move_cat, the_e.move_cat) the_unit.training_cat = max(the_unit.training_cat, the_e.training_cat) if the_e.category == equipment.cat_list.index("Boat hull"): the_unit.type_cat = unit.categories.index("Ship") elif the_e.category == equipment.cat_list.index("Balloon"): the_unit.type_cat = unit.categories.index("Airship") else: pass # Work out categories if ranged and melee: the_unit.weapon_cat = unit.weapon_categories.index("Melee and Ranged") elif ranged and not melee: the_unit.weapon_cat = unit.weapon_categories.index("Ranged") elif melee and not ranged: the_unit.weapon_cat = unit.weapon_categories.index("Melee") else: the_unit.weapon_cat = unit.weapon_categories.index("Neither") # Query queries.append("""UPDATE units SET transport = {transport}, move_type = {move_type}, move_speed = {move_speed}, crew = {crew}, type_cat = {type_cat}, weapon_cat = {weapon_cat}, armour_cat = {armour_cat}, move_cat = {move_cat}, training_cat = {training_cat} WHERE id = {id};""".format( transport = the_unit.transport, move_type = the_unit.move_type, move_speed = the_unit.move_speed, crew = the_unit.crew, type_cat = the_unit.type_cat, weapon_cat = the_unit.weapon_cat, armour_cat = the_unit.armour_cat, move_cat = the_unit.move_cat, training_cat = the_unit.training_cat, id = the_unit.id, )) database.query(cursor, queries)
def build_distance_matrix(the_world, verbose=False): borders = the_world.relations() city_dict = the_world.live_cities() # print(borders) # exit() distance_matrix = {} city_contintent = {} func_start = time.time() i = 0 paths = 0 it = city_dict.items() if verbose: it = cli_f.progressbar(city_dict.items(), "Pathing:", 60, True) worst_land_path = (-1, -1, -1) worst_water_path = (-1, -1, -1) for i1, c1 in it: # i1 = 1224 # c1 = city_dict[i1] started = time.time() links = 0 i += 1 if i1 not in city_contintent: city_contintent[i1] = path_f.get_continent(the_world.cursor, (c1.x, c1.y)) for i2, c2 in city_dict.items(): # i2 = 1280 # c2 = city_dict[i2] # print() # print(city_contintent[i1]) # print(path_f.get_continent(the_world.cursor, (c2.x, c2.y))) # A city can't trade with itself... if i2 == i1: continue # Check we've not already done this if (i1, i2) in distance_matrix: continue # Check borders # [Host][Visitor] # if borders.get[c2.team][c1.team] <= team.border_states.index("Closed"): if the_world.get_border(c2.team, c1.team) <= team.border_states.index("Closed"): continue # if borders[c1.team][c2.team] <= team.border_states.index("At war"): if the_world.get_border(c1.team, c2.team) <= team.border_states.index("At war"): continue # Get continent stuff if i2 not in city_contintent: city_contintent[i2] = path_f.get_continent(the_world.cursor, (c2.x, c2.y)) # Reset distance dist = None crow_dist = path_f.pythagoras_cities(c1, c2) # If on same continent if city_contintent[i1] == city_contintent[i2] and crow_dist < sad_rules.max_crow_dist_land: if crow_dist <= sad_rules.min_trade_distance: dist = DeadPath(sad_rules.min_trade_distance) else: path_time = time.time() try: dist = path_f.path(the_world.cursor, [(c1.x, c1.y), (c2.x, c2.y)], move_speed="Merchant", move_type="Merchant", exception_in_timeout=True, timeout_limit=1000) paths += 1 except Exception as e: print("Trying to path %s (%d) to %s (%d)" % (c1.name, i1, c2.name, i2)) print("Continent %s to %s" % (city_contintent[i1], city_contintent[i2])) raise path_time = time.time() - path_time if path_time > worst_land_path[2]: worst_land_path = ((c1.x, c1.y), (c2.x, c2.y), path_time, "points={0}%2C+{1}%2C+{2}%2C+{3}&move_speed=Merchant&move_type=Merchant".format( c1.x, c1.y, c2.x, c2.y )) # If both are ports then we can try the water if c1.port and c2.port and crow_dist < sad_rules.max_crow_dist_water: path_time = time.time() try: dist_sea = path_f.path(the_world.cursor, [(c1.x, c1.y), (c2.x, c2.y)], move_speed="Sailing", move_type="Sail", exception_in_timeout=True) paths += 1 except Exception as e: print("Trying to path %s (%d) to %s (%d)" % (c1.name, i1, c2.name, i2)) raise path_time = time.time() - path_time if path_time > worst_water_path[2]: worst_water_path = ((c1.x, c1.y), (c2.x, c2.y), path_time, "points={0}%2C+{1}%2C+{2}%2C+{3}&move_speed=Sailing&move_type=Sail".format( c1.x, c1.y, c2.x, c2.y )) # Now pick the fastest if dist == None or dist.time_cost > dist_sea.time_cost: dist = dist_sea # Is it none? if dist == None: time_cost = 99999 else: time_cost = sad_rules.trade_distance(dist.time_cost) links += 1 # if borders[c2.team][c1.team] == team.border_states.index("Segregated"): if the_world.get_border(c2.team, c1.team) <= team.border_states.index("Segregated"): time_cost *= sad_rules.segregated_multiplier if time_cost > sad_rules.max_trade_travel_time: continue distance_matrix[(i1, i2)] = time_cost # If we have the same borders round the other way then we can skip this path later # if borders[c2.team][c1.team] == borders[c1.team][c2.team]: if the_world.get_border(c2.team, c1.team) == the_world.get_border(c1.team, c2.team): distance_matrix[(i2, i1)] = distance_matrix[(i1, i2)] # print("%d of %d in %ss (%d links)" % (i, len(city_dict), round(time.time() - started, 2), links)) """ Origional Tried 103,505 paths Completed in 446 seconds After applying: "if (i1, i2) in distance_matrix" with same border checking Tried 79,979 paths Completed in 338 seconds After dropping the timeout exception from 10k to 1k Tried 79,979 paths Completed in 335 seconds After adding in the min distance (10) Tried 79,958 paths Completed in 337 seconds Adding in dead tiles and a smaller (10 not 1000) move cost Tried 79,958 paths Completed in 336 seconds """ # Some stats stuff if verbose: print("Worst land path: %s -> %s in %s = http://localhost/rob3/web.py?mode=path_map&%s" % worst_land_path) print("Worst water path: %s -> %s in %s = http://localhost/rob3/web.py?mode=path_map&%s" % worst_water_path) total_time = time.time() - func_start print("Tried %s paths in %s seconds, avg %ss per path or %s paths per second" % (format(paths, ','), int(total_time), round(total_time/paths, 3), round(paths/total_time, 2))) # Now to save it q = "INSERT INTO trade_distances (city_1, city_2, distance) values %s;" % ",".join( ["(%d, %d, %d)" % (c[0], c[1], d) for c, d in distance_matrix.items()] ) the_world.cursor.execute("DELETE FROM trade_distances") if verbose: print("Completed in %d seconds" % int(time.time() - func_start)) the_world.cursor.execute(q)
def check_army_bases(cursor, verbose): team_dict = team_q.get_all_teams(cursor) army_dict = army_q.get_armies_from_team_list(cursor, list(team_dict.keys())) city_dict = city_q.get_live_cities(cursor) relations = team_q.get_relations(cursor)# [Host][Visitor] # Build up a shortlist dict of cities by team city_by_team = {} for team_id, the_team in team_dict.items(): if team_id not in city_by_team: city_by_team[team_id] = [] for city_id, the_city in city_dict.items(): if the_city.team == team_id or relations.get(the_city.team, {}).get(team_id, {}).get('border', team_dict[the_city.team].default_borders) >= team.border_states.index("Allied"): city_by_team[team_id].append(city_id) # Now to run through the armies and find their paths new_bases = set() # for i in progressbar(range(15), "Computing: ", 40): # for army_id, the_army in army_dict.items(): if verbose: it = cli_f.progressbar(army_dict.items(), "military_check.check_army_bases: ", 40, with_eta = True) else: it = army_dict.items() for army_id, the_army in it: army_terrain = mapper_q.get_terrain(cursor, the_army.x, the_army.y) for city_id in city_by_team[the_army.team]: if army_terrain < 1: if not the_city.port: continue the_city = city_dict[city_id] if the_city.dead > 0: continue dist = path_f.pythagoras((the_army.x, the_army.y), (the_city.x, the_city.y)) if dist < 10: the_army.base = city_id the_army.distance = (dist/map_data.movement_speeds['Marching'])*10# Distance over speed in km, 1 distance unit is 10k new_bases.add(army_id) # Extend the search a little if army_id not in new_bases: for city_id in city_by_team[the_army.team]: if army_terrain < 1: if not the_city.port: continue the_city = city_dict[city_id] dist = path_f.pythagoras((the_army.x, the_army.y), (the_city.x, the_city.y)) if dist < 30: the_army.base = city_id the_army.distance = (dist/map_data.movement_speeds['Marching'])*10# Distance over speed in km, 1 distance unit is 10k new_bases.add(army_id) # Extend the search a little if army_id not in new_bases: for city_id in city_by_team[the_army.team]: if army_terrain < 1: if not the_city.port: continue the_city = city_dict[city_id] dist = path_f.pythagoras((the_army.x, the_army.y), (the_city.x, the_city.y)) if dist < 60: the_army.base = city_id the_army.distance = (dist/map_data.movement_speeds['Marching'])*10# Distance over speed in km, 1 distance unit is 10k new_bases.add(army_id) # If we can't find an easy solution we start pathing if army_id not in new_bases: fastest_path = (-1, 9999999) for city_id in city_by_team[the_army.team]: the_city = city_dict[city_id] # Small cities won't support an army a long way away right? if the_city.size < 5000: continue # Is it a fleet? if army_terrain < 1: if not the_city.port: continue # Now lets try water dist = path_f.path(cursor, ((the_army.x, the_army.y), (the_city.x, the_city.y)), move_speed="Sailing", move_type="Sail") if dist.time_cost < fastest_path[1]: fastest_path = (city_id, dist.time_cost) else: # I'm sure there's a way to improve this... dist = path_f.path(cursor, ((the_army.x, the_army.y), (the_city.x, the_city.y)), move_speed="Marching", move_type="Medium foot") if dist.time_cost == 0: continue # if army_id == 960 and city_id == 1098: # print("") # print(dir(dist)) # print(((the_army.x, the_army.y), (the_city.x, the_city.y))) # print(dist.time_cost) # print(dist.walk_distance) # print(len(dist.steps)) # print("") if dist.time_cost < fastest_path[1]: fastest_path = (city_id, dist.time_cost) the_army.base = fastest_path[0] the_army.distance = fastest_path[1] new_bases.add(army_id) # Reset all armies query = """UPDATE armies SET base = -1, distance = -1 WHERE garrison = 0;""" try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) for a in new_bases: query = """UPDATE armies SET base = %d, distance = %d WHERE id = %d;""" % (army_dict[a].base, army_dict[a].distance, a) try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) # Garrisons automatically go to their city query = """UPDATE armies SET base = garrison, distance = 0 WHERE garrison > 0;""" try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query))
def run_orders(options): start_time = time.time() cursor = database.get_cursor() cursor.track_queries = True the_world = spy_world.Spy_world(cursor) team_dict = the_world.active_teams() # Run orders #------------------------ print(database.shell_text("Running orders"), end="") queries, orders, debug = [], ["Team orders\n"], [] the_world.prep_for_orders() try: player_updates = {} the_orders = order_post_f.get_turn_orders(cursor, the_world) blocks = [] # for o in the_orders: for o in cli_f.progressbar(the_orders, "Splitting: ", 60, True): o.split() blocks.extend(o.blocks) # Setup # for b in blocks: for b in cli_f.progressbar(blocks, "Setting up: ", 60, True): b.setup() b.always_debug = True # Execution, in order of priority for priority in order_block.priorities: c = 0 for b in blocks: if b.priority != priority: continue try: b.execute() except Exception as e: print("") print(b.title_name) print(the_world.teams()[b.team].name) print("\n".join(cursor.queries[-5:-1])) print("") raise # Ensure we've handled all blocks for b in blocks: if not b.handled: raise Exception("Block with priority '%s' not handled" % b.priority) team_output = {} manual_output = {} team_debug = {} team_failures = {} for b in cli_f.progressbar(blocks, "Running Blocks: ", 60, True): # for b in blocks: if b.team not in team_output: team_output[b.team] = [] if b.team not in team_debug: team_debug[b.team] = [] if b.team not in team_failures: team_failures[b.team] = [] if b.team not in manual_output: manual_output[b.team] = [] # Player activity needs to get updated player_updates[b.post.player] = b.post.team # team_output[b.team].append("[o]%s[/o]" % b.title_name) team_output[b.team].append("\n".join(b.results)) team_output[b.team].append("") if b.manual_handle: manual_output[b.team].append("\n".join(b.results)) manual_output[b.team].append("") # Failures if len(b.failures) > 0: team_failures[b.team].append("\n".join(b.failures)) team_failures[b.team].append("") # Debug team_debug[b.team].append(b.debug[0]) team_debug[b.team].append("\n---\n".join(b.debug[1:len(b.debug)])) team_debug[b.team].append("") # Foreign results for team_id, res in b.foreign_results.items(): if team_id not in team_output: team_output[team_id] = [] team_output[team_id].insert(0, "") team_output[team_id].insert(0, "\n".join(res)) # Queries for team_id, fqueries in b.foreign_queries.items(): queries.extend(fqueries) queries.extend(b.queries) for team_id, the_team in team_dict.items(): if the_team.ir: continue orders.append("""# %s ###################################################################### [fullbox=#EEF,#AAF][h4]Turn %d Results[/h4][/fullbox] [url=http://woarl.com/stats/%s.html]Rob results[/url] """ % (the_team.name, common.current_turn(), team_f.team_hash(the_team.name))) if team_id in team_output: if team_id in manual_output: # orders.extend(team_output[team_id]) orders.extend(manual_output[team_id]) if team_id in team_debug: debug.extend(team_debug[team_id]) # Update player activity database.query(cursor, player_f.update_player_activity(player_updates)) # Save results results_f.save_results(cursor, team_output) results_f.save_failures(cursor, team_failures) # Now we work out the costs team_costs = {} for t, the_team in team_dict.items(): r = res_dict.Res_dict(the_team.resources) queries.extend(r.make_set_queries(t)) # Write queries to file f = open('%s/script_output/queries.sql' % common.data['server_fpath'], 'w') f.write("\n".join(queries)) f.close() # Write orders to file f = open('%s/script_output/orders.txt' % common.data['server_fpath'], 'w') f.write("\n".join(orders)) f.close() # Write debug to file f = open('%s/script_output/debug.txt' % common.data['server_fpath'], 'w') f.write("Team orders\n\n") f.write("\n".join(debug)) f.close() except Exception as e: print(database.shell_text("[r]Failure[/r]")) print(database.shell_text("[r]Re run as 'rob3 start -l True[/r]'")) raise # print(database.shell_text(" - [g]Done[/g]")) # os.system('mate %s' % '%s/queries.sql' % common.data['server_fpath']) # os.system('mate %s' % '%s/orders.txt' % common.data['server_fpath']) # Failable orders failable = ( re.compile(r'DELETE FROM squads WHERE id = [0-9]*;?'), ) failed_queries = [] # Execute order queries #------------------------ # print(database.shell_text("Executing order queries"), end="") for q in cli_f.progressbar(queries, "Running queries: ", 60, True): # for q in queries: if q == '': continue if q[0:2] == '--': continue try: cursor.execute(q) except Exception as e: ignorable = False for f in failable: if f.search(q) != None: ignorable = True failed_queries.append(q) if not ignorable: for f in failable: print("") print(f.search(q)) print("") cursor.execute('ROLLBACK') print(database.shell_text(" - [r]Failure[/r]")) print("Query: %s\n" % q) print(database.shell_text("[r]Re run as 'rob3 start -l True'[/r]")) raise # print(database.shell_text(" - [g]Done[/g]")) if len(failed_queries) > 0: print("Failed queries") print("\n".join(failed_queries)) # Build up a dict of the queries query_dict = {} for q in cursor.queries: if q in ("BEGIN", "COMMIT", "ROLLBACK"): continue if q not in query_dict: query_dict[q] = 0 query_dict[q] += 1 # What's our most popular query? pop_count, pop_query = 0, "" for q, c in query_dict.items(): if c > pop_count: pop_count = c pop_query = q print("\n\n--- Info ---") print("Time taken: %s" % str(round(time.time() - start_time, 3))[0:5]) print("Queries: %d" % len(cursor.queries)) print("Uniques: %d" % len(set(cursor.queries))) print("Most queried: %s (%d)" % (pop_query, pop_count)) # Verbose mode #------------------------ if options.verbose: cursor.execute("ROLLBACK") print("Rolled back") else: cursor.execute("COMMIT") print("Startup scripts executed") os.system("open %s/script_output/orders.txt" % common.data['server_fpath'])
def find_buys(w, city_dict, verbose=True): for city_id, the_city in city_dict.items(): the_city.needs_cache = the_city.current_demands() # Discover if verbose: it = cli_f.progressbar(range(0, config['hops']+1), "Hopping: ", 60, True) else: it = range(0, config['hops']+1) for h in it: for city_id, the_city in city_dict.items(): _discover(w, city_dict, the_city, h) # Find buys if verbose: it = cli_f.progressbar(city_dict.items(), "Finding buys: ", 60, True) else: it = city_dict.items() for city_id, the_city in it: needs = the_city.current_demands() offers = {k:[] for k in needs} # For each city we know, we ask them what price they can do for us for c, d in the_city.connections.items(): for r in needs: if city_dict[c].best_price[config['hops']][r][0] > 1000: continue # Price is made from price saved at other city times the get_price multiplier offer_price = get_price(w, the_city, city_dict[c]) * city_dict[c].best_price[config['hops']][r][0] availiable = the_city.wealth/len(needs) amount = min(availiable/offer_price, -the_city.goods[r]) offers[r].append((offer_price, list(city_dict[c].best_price[config['hops']][r][1]) + [the_city.id], amount)) # Now to turn them into actual Buys for r in needs: availiable = the_city.wealth/len(needs) amount_needed = -the_city.goods[r] sources_used = [] acceptable_buy = True while acceptable_buy: acceptable_buy = False if availiable <= 0 or amount_needed <= 0: continue best_offer = None best_price = 99999 for i, the_offer in enumerate(offers[r]): price, path, amount = the_offer # If we have already used this source then we can look elsewhere if path[0] in sources_used: continue # Compare if price < best_price: best_offer = i best_price = price # Now assign our accepted offer if best_offer == None: continue acceptable_buy = True accepted_offer = offers[r][best_offer] del(offers[r][best_offer]) # Add it to the sells sources_used.append(accepted_offer[1][0]) amount_needed -= accepted_offer[2] city_dict[accepted_offer[1][0]].sells.append((r, accepted_offer[1], accepted_offer[2]))
def find_buys(w, city_dict, verbose=True): # city_dict = w.live_cities() # End point stopper # w.suppliers = {r:set() for r in sad_rules.res_list} # for city_id, the_city in city_dict.items(): # the_city.best_price = {} # # for r in sad_rules.res_list: # if the_city.goods[r] > 0: # w.suppliers[r].add(city_id) for city_id, the_city in city_dict.items(): the_city.needs_cache = the_city.current_demands() if verbose: it = cli_f.progressbar(range(0, config['hops']+1), "Hopping: ", 60, True) else: it = range(0, config['hops']+1) for h in it: # for h in range(0, max_hops+1): # for city_id, the_city in cli_f.progressbar(city_dict.items(), "Hopping %d: " % h, 60, True): for city_id, the_city in city_dict.items(): _discover(w, city_dict, the_city, h) if verbose: it = cli_f.progressbar(city_dict.items(), "Finding buys: ", 60, True) else: it = city_dict.items() for city_id, the_city in it: if the_city.wealth <= 5: continue needs = the_city.current_demands() offers = {} for r in needs: offers[r] = [] # For each supply we want for c, d in the_city.connections.items(): if city_id in city_dict[c].connections: for r in needs: if city_dict[c].best_price[config['hops']][r][0] > 1000: continue # Price is made from price saved at other city times the get_price multiplier offer_price = get_price(w, the_city, city_dict[c]) * city_dict[c].best_price[config['hops']][r][0] availiable = the_city.wealth/len(needs) amount = min(availiable/offer_price, -the_city.goods[r]) offers[r].append((offer_price, list(city_dict[c].best_price[config['hops']][r][1]) + [the_city.id], amount)) # Now to turn them into Buys for r in needs: availiable = the_city.wealth/len(needs) amount_needed = -the_city.goods[r] while amount_needed > 0 and len(offers[r]) > 0: best_offer = None best_price = 99999 for i, o in enumerate(offers[r]): if o[0] < best_price: best_offer = i best_price = o[0] accepted_offer = offers[r][best_offer] del(offers[r][best_offer]) # print("") # print(accepted_offer) city_dict[accepted_offer[1][0]].sells.append((r, accepted_offer[1], accepted_offer[2]))
def check_available(cursor, verbose): the_world = world.World(cursor) unit_dict = the_world.units() unit_q.mass_get_unit_equipment(cursor, the_world._units) equipment_dict = the_world.equipment() city_dict = the_world.cities() terrain_tuples = mapper_q.get_all_terrain(cursor) map_continent_tiles = path_f.get_map_continent_tiles(cursor) # First we need to get the continents and terrains of each team team_dict = {} if verbose: it = cli_f.progressbar(city_dict.items(), "military_check.check_available: ", 40, with_eta = True) else: it = city_dict.items() for city_id, the_city in it: if the_city.dead > 0: continue if the_city.team not in team_dict: team_dict[the_city.team] = Team_lands(the_city.team) city_loc = (the_city.x - (the_city.x % 10), the_city.y - (the_city.y % 10)) city_terrain, city_continent = 0, 0 if city_loc in terrain_tuples: city_terrain = terrain_tuples[city_loc] if city_loc in map_continent_tiles: city_continent = map_continent_tiles[city_loc] team_dict[the_city.team].add_city(city_continent, city_terrain) # Next we'd get the techs too if possible # Now we go through each unit and find out if it's availiable not_available = [] for unit_id, the_unit in unit_dict.items(): if the_unit.team < 2: continue# Skip units that are for all teams # If a team doesn't exist in the dictionary then it's because they've no cities if the_unit.team not in team_dict: # not_available.append(unit_id) continue checked_unit = False the_team = team_dict[the_unit.team] for e in the_unit.equipment: if checked_unit: continue the_equipment = equipment_dict[e] if the_equipment.continent > 0: if the_equipment.terrain > 0: # Need both if not the_team.check_matrix(the_equipment.continent, the_equipment.terrain): not_available.append(unit_id) checked_unit = True else: # Just continent if the_equipment.continent not in the_team.continents: not_available.append(unit_id) checked_unit = True else: if the_equipment.terrain > 0: # Just terrain if the_equipment.terrain not in the_team.terrain: not_available.append(unit_id) checked_unit = True # Now we can check tech level too # self.add_field("terrain", "int")# 0 = Any terrain # self.add_field("tech", "int")# 0 = No tech needed # self.add_field("tech_level", "int")# 0 = No tech needed query = """UPDATE units SET available = True;""" try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query)) if not_available != []: query = """UPDATE units SET available = False WHERE id IN (%s);""" % "".join([str(u) for u in not_available]) try: cursor.execute(query) except Exception as e: raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query))