def main(cursor): name = common.get_val("name", "") campaign = int(common.get_val("campaign", 0)) start = int(common.get_val("start", 0)) duration = int(common.get_val("duration", 0)) btype = int(common.get_val("type", 0)) location = common.get_val("location", "") city = int(common.get_val("city", 0)) # Get location result = battle.battle_coords.search(location) if result != None: x = int(result.groups()[0]) y = int(result.groups()[1]) else: if city > 0: the_city = city_q.get_one_city(cursor, city) x, y = the_city.x, the_city.y else: x, y = 0, 0 # If no name is supplied then it may be from a city if name == '': if city > 0: name = the_city.name else: page_data['Redirect'] = 'setup_campaign&campaign={0}'.format(campaign) return "" # If there is no last battle then we can't use auto pather to work out start time last_battle = battle_q.get_last_battle_from_campaign(cursor, campaign) if start < 0 and last_battle == None: start = 0 # If negative start time then work out travel time if start < 0: waypoints = ((last_battle.x, last_battle.y), (x, y)) b_path = path_f.path(cursor, waypoints, move_speed="Marching", move_type="Medium foot") start = math.ceil(b_path.time_cost) + last_battle.start + last_battle.duration database.query(cursor, battle_f.new_battle(name, campaign, start, duration, x, y, btype=btype, city=city)) # page_data['Redirect'] = 'list_battles&campaign={0}'.format(campaign) page_data['Redirect'] = 'setup_campaign&campaign={0}'.format(campaign) return ""
def relocation_order(the_line, groups, debug=False): results = order_block.default_line_results(the_line) city_dict = the_line.the_world.cities_from_team(the_line.block.team) cities_lookup = the_line.the_world.cities_lookup(lower=True) all_cities = the_line.the_world.cities() city_dict = the_line.the_world.cities_from_team(the_line.block.team) the_team = the_line.the_world.teams()[the_line.block.team] groups["from_city"] = groups["from_city"].strip() groups["to_city"] = groups["to_city"].strip() # Can we find the city? if groups["from_city"].lower() not in cities_lookup: return order_block.fail(results, "there is no city by the name of '%s'" % groups["from_city"]) else: from_city = all_cities[cities_lookup[groups["from_city"].lower()]] if groups["to_city"].lower() not in cities_lookup: return order_block.fail(results, "there is no city by the name of '%s'" % groups["to_city"]) else: to_city = all_cities[cities_lookup[groups["to_city"].lower()]] # Target try: amount = int(groups["amount"].replace(",", "")) except Exception as e: return order_block.fail( results, "there was an error trying to interpret the number '%s'. error: %s" % (groups["amount"], e.args[0]) ) # Type if groups["type"].lower() == "civilians": move_type = "Civilians" elif groups["type"].lower() == "slaves": move_type = "Slaves" # Default result results = order_block.default_line_results( the_line, "%s %s could not be moved from %s to %s because" % (amount, move_type, from_city.name, to_city.name) ) # Strip out all cities too far away, you can only travel for 12 months from_loc = (from_city.x, from_city.y) to_loc = (to_city.x, to_city.y) journey = path_f.path( cursor=the_line.the_world.cursor, waypoints=[from_loc, to_loc], move_speed="Colonists", move_type="Colonists" ) # _journey.time_cost if journey.time_cost > 365: if debug: results["debug"].append("Failed at _journey.time_cost") return order_block.fail( results, "the time required to move between them is too long (%d days)" % journey.time_cost ) # Cost results["cost"] = res_dict.Res_dict("Materials:%s" % (amount / 1000)) # Check affordability affordability = the_team.resources.affordable(results["cost"])[0] if not affordability: return order_block.fail_cost(results) # Are we going overseas? # if mapper_f.get_tile_continent(from_loc) != mapper_f.get_tile_continent(to_loc): # transport_capacity = team_f.team_sea_transport_capacity(block.team) # trips_allowed = math.floor(365/float(journey_time)) # # if (amount > transport_capacity) and (amount*2 > transport_capacity * trips_allowed): # results = "%s could not be relocated from %s to %s amount of overseas transport available is too small" % (amount, the_from_city.city_name, the_to_city.city_name) # return results, queries, order_cost # _city_size if move_type == "Civilians": if from_city.population < amount: if debug: results["debug"].append("Failed at _city_size_civilians") results["debug"].append("Population: %s" % from_city.population) results["debug"].append("Slaves: %s" % from_city.slaves) results["debug"].append("Amount: %s" % amount) return order_block.fail(results, "the city is not big enough to send that many civilians") from_city.population -= amount to_city.population += amount elif move_type == "Slaves": if from_city.slaves < amount: if debug: results["debug"].append("Failed at _city_size_slaves") results["debug"].append("Population: %s" % from_city.population) results["debug"].append("Slaves: %s" % from_city.slaves) results["debug"].append("Amount: %s" % amount) return order_block.fail(results, "the city is not big enough to send that many slaves") from_city.slaves -= amount to_city.slaves += amount results["queries"].extend(city_f.make_relocation_query(from_city.id, to_city.id, amount, move_type)) results["results"].append( "%s %s were successfully moved from %s to %s" % (amount, move_type, from_city.name, to_city.name) ) # Apply cost the_team.resources -= results["cost"].discrete() return order_block.success(results)
def migration_order(the_line, groups, debug=False): results = order_block.default_line_results(the_line) city_dict = the_line.the_world.cities_from_team(the_line.block.team) cities_lookup = the_line.the_world.cities_lookup(lower=True) # Can we find the city? if groups['city'].lower() not in cities_lookup: return order_block.fail(results, "there is no city by the name of '%s'" % groups['city']) else: the_city = city_dict[cities_lookup[groups['city'].lower()]] the_team = the_line.the_world.teams()[the_line.block.team] # Target try: target = (int(groups['x']), int(groups['y'])) except Exception as e: return order_block.fail(results, "%s was not moved because trying to read the target location produced an error: %s" % (groups['city_name'], e.args[0])) # Default result results = order_block.default_line_results(the_line, "%s could not be moved to %s because" % (the_city.name, str(target))) # First we check it's on the same continent, if it's not you can't migrate there our_continent = path_f.get_continent(the_line.the_world.cursor, (the_city.x, the_city.y)) target_continent = path_f.get_continent(the_line.the_world.cursor, target) # Before we path, lets check that they can walk there if our_continent != target_continent: if target_continent == None:# or target_continent == -1: return order_block.fail(results, "the target is the ocean") else: return order_block.fail(results, "the target is on a different island") terrain = mapper_q.get_terrain(the_line.the_world.cursor, target[0], target[1]) if map_data.terrain[terrain] in ('lake', 'XYZ_1', 'XYZ_2', 'XYZ_3'): return order_block.fail(results, "you cannot migrate to that terrain (%s)" % map_data.terrain[terrain]) # Pathing time! journey = path_f.path( cursor=the_line.the_world.cursor, waypoints=[(the_city.x, the_city.y), target], move_speed="Nomads", move_type="Nomads") # Does this take more than a year? travel_time = journey.time_cost actual_target = target current_time = 0 if journey.time_cost > 365: for s in journey.steps: if current_time + s['time_cost'] <= 365: actual_target = s['tile'] current_time += s['time_cost'] travel_time = current_time if actual_target != target: results['results'].append("%s migrated to %s, to migrate to %s will take another %s days" % (the_city.name, str(actual_target), str(target), (journey.time_cost - travel_time))) else: results['results'].append("%s migrated to %s" % (the_city.name, str(target))) # Get the query to make it happen results['queries'].extend(city_f.make_migration_query(the_city.id, actual_target, travel_time)) return order_block.success(results)
def path_order(the_line, groups, debug=False): results = order_block.default_line_results(the_line) if not the_line.block.msn_order: return order_block.fail(results, "Command not valid in live mode") groups['waypoints'] = groups['waypoints'].strip() the_path = groups['waypoints'].replace(": ", "").replace(".", ",") path_split = [x.strip() for x in the_path.split(',')] waypoints = [] for p in path_split: if waypoints == []: waypoints.append([]) elif len(waypoints[-1]) == 2: waypoints.append([]) try: waypoints[-1].append(int(p)) except Exception: return order_block.fail(results, "the coordinates you sent could not be converted") # Get times infantry_time = path_f.path( cursor=the_line.the_world.cursor, waypoints=waypoints, move_speed="Marching", move_type="Medium foot" ).time_cost cavalry_time = path_f.path( cursor=the_line.the_world.cursor, waypoints=waypoints, move_speed="Riding", move_type="Medium cav" ).time_cost airship_time = path_f.path( cursor=the_line.the_world.cursor, waypoints=waypoints, move_speed="Sailing", move_type="Air" ).time_cost ship_time = path_f.path( cursor=the_line.the_world.cursor, waypoints=waypoints, move_speed="Sailing", move_type="Sail" ).time_cost colonist_time = path_f.path( cursor=the_line.the_world.cursor, waypoints=waypoints, move_speed="Colonists", move_type="Colonists" ).time_cost # Print results results['results'] = ["""Time taken to travel from %s to %s is: %s days as infantry %s days as cavalry %s days as airships %s days as ships %s days as colonists""" % (waypoints[0], waypoints[-1], round(infantry_time), round(cavalry_time), round(airship_time), round(ship_time), round(colonist_time), )] return order_block.success(results)
def main(cursor): return "" output = ["""<div style="padding: 5px;">"""] ajax = common.get_val('ajax', 0) if not ajax: page_data['Headers'] = False battle_dict = battle_q.get_battles_from_turn(cursor, common.current_turn()) team_dict = team_q.get_all_teams(cursor) city_dict = city_q.get_all_cities(cursor) output.append("""<table border="0" cellspacing="0" cellpadding="5"> <tr class="row2"> <th>Battle</th> <th>Time</th> <th>Location</th> </tr>""") # Display battles i = -1 for battle_id, the_battle in battle_dict.items(): i += 1 location = "%d, %d" % (the_battle.x, the_battle.y) if i == 0: days_since = "" time_taken = "" distance = "" else: waypoints = ((last_battle.x, last_battle.y), (the_battle.x, the_battle.y)) b_path = path_f.path(cursor, waypoints, move_speed="Marching", move_type="Medium foot") days_since = "Days since last battle: {0}".format(the_battle.start - last_battle.ended) time_taken = "Time taken to travel: {0} days".format(b_path.time_cost) distance = "Distance from last battle: {0}km".format(format(b_path.walk_distance, ',')) output.append(""" <tr class="row0"> <td><strong>{name}</strong></td> <td>{start} : {ended}</td> <td>{location}</td> </tr> <tr class="row1"> <td colspan="3"> {days_since}<br /> {time_taken}<br /> {distance}<br /> </td> </tr> """.format( i=i%2, name=the_battle.name, start=the_battle.start, ended=the_battle.ended, location=location, days_since = days_since, time_taken = time_taken, distance = distance, id=battle_id, )) # Use this to record stuff for the next battle last_battle = the_battle output.append("</table></div>") return "".join(output)
def main(cursor): output = ["""<div style="padding: 5px;">"""] campaign_id = int(common.get_val('campaign', 0)) ajax = common.get_val('ajax', 0) # Used to let us know if there is an issue with the campaign errors = False if campaign_id < 1: return "No campaign selected" if not ajax: page_data['Headers'] = False the_campaign = campaign_q.get_one_campaign(cursor, campaign_id) battle_dict = battle_q.get_battles_from_campaign(cursor, campaign_id) team_dict = team_q.get_all_teams(cursor) city_dict = city_q.get_all_cities(cursor) output.append("""<table border="0" cellspacing="0" cellpadding="5"> <tr class="row2"> <th>Battle</th> <th>Time</th> <th>Location</th> <th colspan="4"> </th> </tr>""") # Display battles i = -1 total_waypoints = [] for battle_id, the_battle in battle_dict.items(): i += 1 location = "%d, %d" % (the_battle.x, the_battle.y) total_waypoints.append((the_battle.x, the_battle.y)) if i == 0: days_since = "" time_taken = "" distance = "" path_map_link = " " else: waypoints = ((last_battle.x, last_battle.y), (the_battle.x, the_battle.y)) b_path = path_f.path(cursor, waypoints, move_speed="Marching", move_type="Medium foot") w_path = path_f.path(cursor, waypoints, move_speed="Sailing", move_type="Sail") if w_path != None: if b_path.time_cost > w_path.time_cost: b_path = w_path days_since = "Days since last battle: {0}".format(the_battle.start - (last_battle.start + last_battle.duration)) time_taken = "Time taken to travel: {0} days".format(int(b_path.time_cost)) distance = "Distance from last battle: {0}km".format(format(b_path.walk_distance, ',')) # Formatting for time taken? if b_path.time_cost > (the_battle.start - (last_battle.start + last_battle.duration)): time_taken = "<span class='neg' style='font-weight:bold;'>%s</span>" % time_taken days_since = "<span class='neg' style='font-weight:bold;'>%s</span>" % days_since errors = True points = str(waypoints).replace('(', '').replace(')', '')#.replace(',', '%2C') path_map_link = '<a href="web.py?mode=path_map&points=%s&move_speed=Marching&move_type=Medium foot" class="block_link">Path link</a>' % points # Battle start start_str = the_battle.start dur_str = the_battle.duration if (the_battle.start + the_battle.duration) > 365: start_str = '<span class="neg" style="font-weight:bold;">%s</span>' % the_battle.start dur_str = '<span class="neg" style="font-weight:bold;">%s</span>' % the_battle.duration errors = True output.append(""" <tr class="row0"> <td><strong>{name}</strong></td> <td>{start} : {duration}</td> <td>{location}</td> <td width="5"> </td> <td colspan="3"> </td> </tr> <tr class="row1"> <td colspan="3"> {days_since}<br /> {time_taken}<br /> {distance}<br /> </td> <td width="5"> </td> <td colspan="3" style="padding:0px;"> {path_map_link} </td> </tr> """.format( i=i%2, name=the_battle.name, start=start_str, duration=dur_str, location=location, days_since = days_since, time_taken = time_taken, distance = distance, path_map_link = path_map_link, id=battle_id, )) # Use this to record stuff for the next battle last_battle = the_battle if errors: error_str = "ERRORS FOUND" else: error_str = "" points = str(tuple(total_waypoints)).replace('(', '').replace(')', '')#.replace(',', '%2C') output.append(""" <tr class="row0"> <td colspan="3" style="font-weight:bold;font-size:1.5em;text-align:center;color:#F00;padding:10px;"> {error_str} </td> <td> </td> <td colspan="3" style="padding:0px;"> {path_link} </td> </tr>""".format( path_link = '<a href="web.py?mode=path_map&points=%s&move_speed=Marching&move_type=Medium foot" class="block_link">Path link</a>' % points, error_str = error_str, )) output.append("</table>") output.append("</div>") return "".join(output)
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 founding_order(the_line, groups, debug=False): results = order_block.default_line_results(the_line) all_cities = the_line.the_world.cities() city_dict = the_line.the_world.cities_from_team(the_line.block.team) cities_lookup = the_line.the_world.cities_lookup(lower=True) the_team = the_line.the_world.teams()[the_line.block.team] team_dict = the_line.the_world.teams() dead_city = -1 # Handles new_city_name = groups['city_name'] supply_list_s = groups['city_list'] size = int(groups['size'].replace(',', '')) if groups['city_type'] != None: city_type = groups['city_type'].lower().strip() else: city_type = None is_port, is_nomadic = False, False if city_type == "port": is_port = True elif city_type == "nomadic": is_nomadic = True # Get the location from the string try: x, y = groups['location'].split(',') x = int(x.strip()) y = int(y.strip()) terrain = mapper_q.get_terrain(the_line.the_world.cursor, x, y) except Exception as e: return order_block.fail(results, "%s was not founded because trying to read the location produced an error: %s" % (groups['city_name'], e.args[0])) # Rule checks #------------------------ results = order_block.default_line_results(the_line, "%s could not be founded at %s because" % (new_city_name, str((x, y)))) # You can't build on water! if map_data.terrain[terrain] in ('water', 'lake', 'XYZ_1', 'XYZ_2', 'XYZ_3'): return order_block.fail(results, "you cannot build on that terrain (%s)" % map_data.terrain[terrain]) # Does it already exist? if new_city_name.lower() in cities_lookup: existing_city = all_cities[cities_lookup[new_city_name.lower()]] try: if not existing_city.dead: return order_block.fail(results, "%s already exists (controlled by %s)" % (new_city_name, team_dict[existing_city.team].name)) else: # Currently all dead cities need a GM to act return order_block.fail(results, "%s already exists as a dead city, contact Teifion to to fix it (ID:%d)" % (new_city_name, cities_lookup[new_city_name.lower()])) if all_cities[cities_lookup[new_city_name.lower()]].team == the_team.id: dead_city = cities_lookup[new_city_name.lower()] else: return order_block.fail(results, "%s already exists as a dead city, contact Teifion to to fix it (ID:%d)" % (new_city_name, cities_lookup[new_city_name.lower()])) except Exception as e: print(new_city_name.lower()) raise # Is it allowed to be a port? if is_port: if map_data.terrain[terrain] != "shore": is_port = False if mapper_q.get_terrain(the_line.the_world.cursor, x-10, y-10) == 0: is_port = True if mapper_q.get_terrain(the_line.the_world.cursor, x-10, y) == 0: is_port = True if mapper_q.get_terrain(the_line.the_world.cursor, x-10, y+10) == 0: is_port = True if mapper_q.get_terrain(the_line.the_world.cursor, x, y-10) == 0: is_port = True if mapper_q.get_terrain(the_line.the_world.cursor, x, y+10) == 0: is_port = True if mapper_q.get_terrain(the_line.the_world.cursor, x+10, y-10) == 0: is_port = True if mapper_q.get_terrain(the_line.the_world.cursor, x+10, y) == 0: is_port = True if mapper_q.get_terrain(the_line.the_world.cursor, x+10, y+10) == 0: is_port = True if not is_port: return order_block.fail(results, "%s that is not next to the sea" % str((x, y))) # Supply list supply_dict_raw = {} if supply_list_s != None: supply_list_s = supply_list_s.split(",") for s in supply_list_s: sls = s.lower().strip() if sls in cities_lookup: supply_dict_raw[cities_lookup[sls]] = 9999999 else: for c in city_dict.keys(): supply_dict_raw[c] = 9999999 # print("") # print(supply_dict_raw) if debug: results['debug'].append("First pass:"******"City ID %d was not in city_dict" % c) return order_block.fail(results, "One or more of the cities used as a source were not valid (ID: %d)" % c) the_city = city_dict[c] if the_city.dead > 0: continue if new_city_continent != path_f.get_continent(the_line.the_world.cursor, (the_city.x, the_city.y)): if not is_port or not the_city.port: if len(supply_dict_raw) == 1: if debug: results['debug'].append("Continent of target: %s" % new_city_continent) results['debug'].append("Continent of supply: %s" % path_f.get_continent(the_line.the_world.cursor, (the_city.x, the_city.y))) if not the_city.port and not is_port: return order_block.fail(results, "the city you supplied is on another contintent and neither this city nor the new one are a port") elif not the_city.port: return order_block.fail(results, "the city you supplied is on another contintent and the existing city is not a port") elif not is_port: return order_block.fail(results, "the city you supplied is on another contintent and the new city is not a port") else: raise Exception("No handle") if not is_port: if debug: results['debug'].append("Skipped %s due to the new city being on another landmass and not a port" % (city_dict[c].name)) elif not the_city.port: if debug: results['debug'].append("Skipped %s due to it not being a port" % (city_dict[c].name)) # We need both to be a port if they're on different landmasses continue path_data = path_f.path(the_line.the_world.cursor, [(the_city.x, the_city.y), (x, y)], move_speed="Sailing", move_type="Sail") supply_dict[c] = path_data.time_cost if debug: results['debug'].append("Added %s to dict with %s (sailing)" % (city_dict[c].name, int(path_data.time_cost))) else:# Same continent path_data = path_f.path(the_line.the_world.cursor, [(the_city.x, the_city.y), (x, y)], move_speed="Colonists", move_type="Colonists") supply_dict[c] = path_data.time_cost if debug: results['debug'].append("Added %s to dict with %s (walking)" % (city_dict[c].name, int(path_data.time_cost))) # Work out if it's in range if supply_dict[c] > 182:# 6 months if debug: results['debug'].append("Removed %s from dict with, it took %s" % (city_dict[c].name, int(supply_dict[c]))) del(supply_dict[c]) if debug: results['debug'].append("\nCities in range:") for k, v in supply_dict.items(): results['debug'].append("%s has %s to offer (travel time %s)" % (city_dict[k].name, city_dict[k].population, int(v))) # results['debug'].append("") cities_changed = True while cities_changed: if len(supply_dict) < 1: if groups['city_list'] == None: return order_block.fail(results, "the cities able to reach the new location were too far away or not large enough") else: return order_block.fail(results, "the cities able to reach the new location from the list provided were too far away or not large enough") cities_to_delete = [] cities_changed = False city_count = len(supply_dict) amount_per_city = math.ceil(size/city_count) for c in supply_dict.keys(): # Check the city size if city_dict[c].population < amount_per_city: # if debug: print("deleted %s (%s) pop:%s < %s" % (c, city_dict[c].name, supply_dict[c], amount_per_city)) cities_to_delete.append(c) cities_changed = True for c in cities_to_delete: del(supply_dict[c]) # Get cost results['cost'] = res_dict.Res_dict("Materials:%s" % (size/1000)) # Check affordability affordability = the_team.resources.affordable(results['cost'])[0] if not affordability and "Materials" not in the_team.overbudget: return order_block.fail_cost(results) # EXECUTION #------------------------ # Queries results['queries'].append("-- Founding %s at %s for team:%d" % (new_city_name, str((x, y)), the_team.id)) if dead_city > 1: results['queries'].extend(city_f.make_remove_dead_city_query(dead_city)) results['queries'].extend(city_f.make_founding_query( the_team.id, new_city_name, (x, y), is_port, is_nomadic, size, supply_dict.keys()) ) # Apply cost for c in supply_dict.keys(): city_dict[c].population -= (size/len(supply_dict)) the_team.resources -= results['cost'].discrete() # Result results['results'].append("%s was successfully founded at %s at a size of %s" % (new_city_name, str((x, y)), size)) return order_block.success(results)
def main(): """Tests a set of paths""" cursor = database.get_cursor() tests = [] # Goes from one end to the other of the Tishrashi desert, nothing special # tests.append(([(267, 1414), (438, 1405)], "Marching", "Medium foot")) # One end of Cayim to the other # tests.append(([(75, 1180), (986, 1664)], "Marching", "Medium foot")) # Top left to bottom right # tests.append(([(-1176, 636), (1276, 2283)], "Sailing", "Sail")) # 3 waypoints tests.append(([(400, 853), (565, 815), (605, 1003)], "Marching", "Medium foot")) # Noamdic test # tests.append(([(110,1190), (930,1690)], "Nomads", "Nomads")) # Round Cantharan tests.append(([(174, 1941), (392, 1965), (400, 2264), (-209, 2276), (-266, 1878), (-43, 1441)], "Sailing", "Sail")) # print("Waypoints: %s -> %s" % (str(p.start_point), str(p.end_point))) # print("Cost: %s" % p.time_cost) # print("Distance: %s" % round(p.distance, 2)) # print("Step count: %d" % len(p.steps)) # print("Steps: ", ", ".join([str(s['tile']) for s in p.steps])) map_path = "http://localhost/rob3/web.py?mode=path_map&" for t in tests: points = [] for w in t[0]: points.append(w[0]) points.append(w[1]) p = path_f.path(cursor, t[0], t[1], t[2]) print("%spoints=%s&move_speed=%s&move_type=%s - %s days, %skm" % ( map_path, ",".join([str(w) for w in points]),# Waypoints t[1].replace(" ", "%20"), t[2].replace(" ", "%20"), p.time_cost, p.walk_distance, )) # We've just got 1 test setup, lets give more info if len(tests) == 1: print("") if p.steps[-1] == p.end_point: print("Success") else: print("Failure") print("Cost: %s" % p.time_cost) total_cost = 0 for i, s in enumerate(p.steps): total_cost += s['time_cost'] print("{i} {cost} {total}".format( i=i, cost=s['time_cost'], total=total_cost, ))
def main(cursor): points = common.get_val('points', "") move_speed = common.get_val('move_speed', "Marching") move_type = common.get_val('move_type', "Medium foot") if points == "": page_data['Header'] = True page_data['Title'] = "Path map" # name, elements = {}, element_order = [], tab_index = -1, onchange="", custom_id = "<>", selected="" speed_dropdown = common.option_box('move_speed', map_data.move_speed_list, selected="Marching") type_dropdown = common.option_box('move_type', map_data.move_type_list, selected="Medium foot") return """ <form action="web.py" method="get" accept-charset="utf-8" style="padding:5px;"> <input type="hidden" name="mode" value="path_map" /> <table border="0" cellspacing="0" cellpadding="5"> <tr> <td><label for="points">Waypoints:</label></td> <td><input type="text" id="points" name="points" value="" size="40"/></td> </tr> <tr> <td><label for="move_speed">Speed:</label></td> <td> {move_speed} </td> </tr> <tr> <td><label for="move_type">Type:</label></td> <td> {move_type} </td> </tr> <tr> <td><input type="submit" value="View" /></td> <td> </td> </tr> </table> </form> {onload} """.format( move_speed=speed_dropdown, move_type=type_dropdown, onload=common.onload("$('#points').focus();") ) try: move_speed = map_data.move_speed_list[int(move_speed)] except Exception as e: pass try: move_type = map_data.move_type_list[int(move_type)] except Exception as e: pass waypoints = [] points_list = points.split(",") for p in range(0, len(points_list), 2): waypoints.append((int(points_list[p]), int(points_list[p+1]))) path_data = path_f.path(cursor, waypoints, move_speed=move_speed, move_type=move_type) float_div = """<div style="background-color:#CCC;position:absolute;top:0px;left:0px;padding:5px;"> <a href="web.py?mode=path_map">Reset</a><br /> Distance: {distance}<br /> Time taken: {time}<br /> </div>""".format( distance = format(path_data.walk_distance, ','), time = path_data.time_cost, ) dimensions = { "left": 999999, "top": 999999, "right": -999999, "bottom": -999999, } # Need to work out how big the map will actually be radius = 300 for s in path_data.steps: dimensions['left'] = min(dimensions['left'], s['tile'][0] - radius) dimensions['right'] = max(dimensions['right'], s['tile'][0] + radius) dimensions['top'] = min(dimensions['top'], s['tile'][1] - radius) dimensions['bottom'] = max(dimensions['bottom'], s['tile'][1] + radius) # Make map object the_map = mapper.Map_maker() the_map.path_data = path_data the_map.left = max(dimensions['left'], the_map.left) the_map.right = min(dimensions['right'], the_map.right) the_map.top = max(dimensions['top'], the_map.top) the_map.bottom = min(dimensions['bottom'], the_map.bottom) onclick_js = """ var map_x = parseInt(document.getElementById('labelHideX').innerHTML); var map_y = parseInt(document.getElementById('labelHideY').innerHTML); use_map_xy(map_x, map_y);""" source_dict = { # "build": False, "onclick_js": onclick_js, # "map_click_handler": map_click_handler, "output": the_map.map_grid(cursor), } source_dict['map_legend'] = '' source_dict["left"] = the_map.left * 2.5 source_dict["right"] = the_map.right source_dict["top"] = the_map.top * 2.5 source_dict["bottom"] = the_map.bottom source_dict["map_width"] = the_map.width*2.5 source_dict["map_height"] = the_map.height*2.5 x_diff = map_data.dimensions['left'] - the_map.left y_diff = map_data.dimensions['top'] - the_map.top source_dict["margin_left"] = (x_diff + map_data.dimensions['margin_left'])*2.5 source_dict["margin_top"] = (y_diff + map_data.dimensions['margin_top'])*2.5 return "%s%s" % (float_div, mapper.map_source(source_dict))
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)