Exemplo n.º 1
0
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 ""
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
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">&nbsp;</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 = "&nbsp;"
		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&amp;points=%s&amp;move_speed=Marching&amp;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">&nbsp;</td>
			
			<td colspan="3">
				&nbsp;
			</td>
		</tr>
		<tr class="row1">
			<td colspan="3">
				{days_since}<br />
				{time_taken}<br />
				{distance}<br />
			</td>
			
			<td width="5">&nbsp;</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>&nbsp;</td>
		<td colspan="3" style="padding:0px;">
			{path_link}
		</td>
	</tr>""".format(
		path_link = '<a href="web.py?mode=path_map&amp;points=%s&amp;move_speed=Marching&amp;move_type=Medium foot" class="block_link">Path link</a>' % points,
		error_str = error_str,
	))
	
	
	output.append("</table>")
	output.append("</div>")
	
	return "".join(output)
Exemplo n.º 7
0
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))
Exemplo n.º 8
0
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)
Exemplo n.º 9
0
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,
				))
Exemplo n.º 10
0
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>&nbsp;</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))
Exemplo n.º 11
0
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)