예제 #1
0
파일: city_f.py 프로젝트: Teifion/Rob3
def overlap(c1, c2, debug=False):
	if not _check_area(c1, c2, debug=debug):
		return 0
	
	acos = math.acos
	sqrt = math.sqrt
	
	r = map_data.map_image_size(c1.size)/5
	R = map_data.map_image_size(c2.size)/5
	d = path_f.pythagoras((c1.x, c1.y), (c2.x, c2.y))
	
	if d > r + R: return 0
	if d == 0: return math.pi * max((r*r), (R*R))
	
	# r is the radius of circle 1
	# R is the radius of circle 2
	# d is the distance of the centre of circle 2 from the centre of circle 1.
	# cos-1 is the inverse cosine operator.
	
	try:
		a = r**2 * acos((d**2 + r**2 - R**2) / (2 * d * r))
		b = R**2 * acos((d**2 + R**2 - r**2) / (2 * d * R))
		c = (-d + r + R) * (d + r - R) * (d - r + R) * (d + r + R)
		c = sqrt(c) / 2
	except Exception as e:
		# It may be that the smaller is completely covered by the bigger
		# C = centre, R = Radius
		# C1 -- C2 -- R2 ----- R1
		
		R = map_data.map_image_size(c1.size)/2
		S = map_data.map_image_size(c2.size)
		D = path_f.pythagoras(c1, c2)
		
		# Area = pi * r^2
		if R > S + D:
			return math.pi * (S/2) * (S/2)
		
		
		print("")
		print("Error overlapping %s (%d) with %s (%d)" % (c1.name, c1.id, c2.name, c2.id))
		print(r)
		print(R)
		print(d)
		
		raise
	a = r**2 * acos((d**2 + r**2 - R**2) / (2 * d * r))
	b = R**2 * acos((d**2 + R**2 - r**2) / (2 * d * R))
	c = (-d + r + R) * (d + r - R) * (d - r + R) * (d + r + R)
	c = sqrt(c) / 2
	
	# print(a + b - c)
	
	return (a + b - c)
예제 #2
0
	def major():
		city_dict	= the_world.cities()
		failures	= []
		
		for city_id_1, the_city_1 in city_dict.items():
			if the_city_1.team != the_team.id or the_city_1.dead: continue
			cities_within_range = 0
			
			for city_id_2, the_city_2 in city_dict.items():
				if the_city_2.team != the_team.id or the_city_2.dead: continue
				if city_id_2 == city_id_1: continue
				
				distance = path_f.pythagoras((the_city_1.x, the_city_1.y), (the_city_2.x, the_city_2.y))
				
				if distance <= 150:
					cities_within_range += 1
			
			if cities_within_range < 2:
				failures.append(the_city_1.name)
		
		if len(failures) < 1:
			info.append("<span class='pos'>Major:</span> All of your cities are within 150 units of at least two other of your cities")
			return favour_rewards["major_pos"]
		else:
			if len(failures) > 1:
				info.append("<span class='neg'>Major:</span> The following cities are not within 150 units of at least two other of your cities: %s and %s" % (", ".join(failures[0:-1]), failures[-1]))
			else:
				info.append("<span class='neg'>Major:</span> The city of %s not within 150 map units of at least two of your other cities" % (failures[0]))
			return favour_rewards["major_neg"]
예제 #3
0
	def major():
		team_dict_c			= the_world.teams()
		city_dict_c			= the_world.cities()
		operatives_dict_c	= the_world.operatives()
		
		the_world.operatives_in_city(0)
		operatives_by_city	= the_world._operatives_in_city
		
		# First we want a list of all our cities
		our_city_list = []
		their_city_list = []
		
		for city_id, the_city in city_dict_c.items():
			if the_city.dead > 0: continue
			
			if the_city.team == the_team.id:
				our_city_list.append(city_id)
			elif common.current_turn() - the_city.founded > 2:
				their_city_list.append(city_id)
		
		nations_within_range	= set()
		nations_infiltrated		= set()
		
		# New we compare each with each
		for our_city_id in our_city_list:
			our_city = city_dict_c[our_city_id]
			
			for their_city_id in their_city_list:
				their_city = city_dict_c[their_city_id]
				
				# Is this city within range?
				distance = path_f.pythagoras((our_city.x, our_city.y), (their_city.x, their_city.y))
				
				if distance <= 1000:
					nations_within_range.add(their_city.team)
					
					if their_city_id in operatives_by_city:
						city_has_op = False
						for o in operatives_by_city[their_city_id]:
							if operatives_dict_c[o].team == the_team.id and operatives_dict_c[o].died < 1:
								city_has_op = True
						
						if city_has_op:
							nations_infiltrated.add(their_city.team)
		
		# Now to find out what nations we fail at
		failures = []
		for t in nations_within_range:
			if t not in nations_infiltrated:
				failures.append(team_dict_c[t].name)
		
		if len(failures) == 0:
			info.append("<span class='pos'>Major:</span> You have operatives within all nations within 1000 units of your cities" % (operative_percentage))
			return favour_rewards["major_pos"]
		else:
			if len(failures) > 1:
				info.append("<span class='neg'>Major:</span> The following nations do not have operatives in them: %s and %s" % (", ".join(failures[0:-1]), failures[-1]))
			else:
				info.append("<span class='neg'>Major:</span> The nation of %s does not have an operative in it" % (failures[0]))
			return favour_rewards["major_neg"]
예제 #4
0
	def negative():
		city_dict		= the_world.cities()
		team_dict		= the_world.teams()
		deities_lookup	= the_world.deities_lookup()
		
		failures = []
		for k, our_city in city_dict.items():
			city_failure = ""
			
			if our_city.team != the_team.id: continue# We only want to use our own cities thanks
			if our_city.dead: continue
			
			for k, their_city in city_dict.items():
				if city_failure != "": continue# We've failed this one already
				if deities_lookup['Arl'] not in team_dict[their_city.team].get_deities(the_world.cursor): continue
				
				if their_city.team == the_team.id: continue# Ignore ourselves
				if their_city.dead: continue# Ignore dead cities
				
				distance = path_f.pythagoras((our_city.x, our_city.y), (their_city.x, their_city.y))
				
				if distance < 200:
					city_failure = their_city.name
					failures.append("%s (%s)" % (our_city.name, city_failure))
		
		if len(failures) < 1:
			info.append("<span class='pos'>Negative:</span> No Arl aligned cities are within 200 units of any of your cities")
			return favour_rewards["negative_pos"]
		else:
			if len(failures) > 1:
				info.append("<span class='neg'>Negative:</span> The following cities are within 200 units of an Arl aligned city: %s and %s" % (", ".join(failures[0:-1]), failures[-1]))
			else:
				info.append("<span class='neg'>Negative:</span> The city of %s is within 200 units of an Arl aligned city" % (failures[0]))
			return favour_rewards["negative_neg"]
예제 #5
0
	def negative():
		team_dict		= the_world.teams()
		deities_lookup	= the_world.deities_lookup()
		city_dict		= the_world.cities()
		
		city_in_range = False
		for city_id_1, the_city_1 in city_dict.items():
			if the_city_1.team != the_team.id or the_city_1.dead: continue
			if city_in_range: continue
			
			for city_id_2, the_city_2 in city_dict.items():
				if the_city_2.dead or city_id_2 == city_id_1: continue
				if deities_lookup['Soag chi'] in team_dict[the_city_2.team].get_deities(the_world.cursor): continue
				
				distance = path_f.pythagoras((the_city_1.x, the_city_1.y), (the_city_2.x, the_city_2.y))
				
				if distance < 50:
					city_in_range = True
		
		if city_in_range:
			info.append("<span class='pos'>Negative:</span> You have at least one city within 50 map units of a city that does not follow Soag chi")
			return favour_rewards["negative_pos"]
		else:
			info.append("<span class='neg'>Negative:</span> None of your cities are within 50 map units of a city that does not follow Soag chi")
			return favour_rewards["negative_neg"]
예제 #6
0
	def minor():
		city_dict = the_world.cities()
		
		failures = []
		for k, our_city in city_dict.items():
			city_is_within_range = False
			
			if our_city.team != the_team.id: continue# We only want to use our own cities thanks
			if our_city.dead: continue
			
			for k, their_city in city_dict.items():
				if city_is_within_range: continue# We've approved this one already
				
				if their_city.team == the_team.id: continue# Ignore ourselves
				if their_city.dead: continue# Ignore dead cities
				
				distance = path_f.pythagoras((our_city.x, our_city.y), (their_city.x, their_city.y))
				
				if distance < 100: city_is_within_range = True
			
			if not city_is_within_range:
				failures.append(our_city.name)
		
		if len(failures) == 0:
			info.append("<span class='pos'>Minor:</span> All of your cities are within 100 units of a city from another nation")
			return favour_rewards["minor_pos"]
		else:
			if len(failures) > 1:
				info.append("<span class='neg'>Minor:</span> The following cities are not within 100 units of a city from another nation: %s and %s" % (", ".join(failures[0:-1]), failures[-1]))
			else:
				info.append("<span class='neg'>Minor:</span> The city %s is not within 100 units of a city from another nation" % (failures[0]))
			return favour_rewards["minor_neg"]
예제 #7
0
파일: path_t.py 프로젝트: Teifion/Rob3
	def test_pythagoras(self):
		data_set = []
		data_set.extend(self.tuple_vals)
		data_set.extend(self.city_vals)
		data_set.extend(self.pure_vals)
		
		for a, b, expected in data_set:
			r = path_f.pythagoras(a, b)
			self.assertAlmostEqual(r, expected, places=2)
예제 #8
0
파일: city_rules.py 프로젝트: Teifion/Rob3
def wonder_build_rate(assist_city, wonder_city):
    distance = path_f.pythagoras((assist_city.x, assist_city.y), (wonder_city.x, wonder_city.y))

    # Port allows for far greater distances
    if assist_city.port and assist_city.port:
        distance *= 0.2

    supply_size = (assist_city.population + assist_city.slaves) / 1000.0

    return int(math.floor(max(supply_size - distance, 0)))
예제 #9
0
	def major():
		team_dict			= the_world.teams()
		deities_lookup		= the_world.deities_lookup()
		city_dict			= the_world.cities()
		operatives_from_team	= the_world.operatives_from_team(the_team.id)
		
		# We want to build a cache for our operatives in which cities
		cities_with_our_ops = []
		for o, the_op in operatives_from_team.items():
			cities_with_our_ops.append(the_op.city)
			
		cities_with_our_ops = set(cities_with_our_ops)
		
		# First we want a list of all our cities
		our_city_list = []
		their_city_list = []
		
		failures = []
		for city_id, the_city in city_dict.items():
			if the_city.dead > 0: continue
			if common.current_turn() - the_city.founded <= 3: continue
			
			if the_city.team == the_team.id:
				our_city_list.append(city_id)
			else:
				# If they follow Soag chi then we can skip them
				if deities_lookup['Soag chi'] in team_dict[the_city.team].get_deities(the_world.cursor): continue
				their_city_list.append(city_id)
		
		# New we compare each with each
		for our_city_id in our_city_list:
			our_city = city_dict[our_city_id]
			
			for their_city_id in their_city_list:
				their_city = city_dict[their_city_id]
				
				# Is this city within range?
				distance = path_f.pythagoras((our_city.x, our_city.y), (their_city.x, their_city.y))
				
				if distance <= 100:
					# Check for operative
					if their_city_id not in cities_with_our_ops:
						failures.append(their_city.name)
		
		# failures = list(set(failures))
		
		if len(failures) < 1:
			info.append("<span class='pos'>Major:</span> All cities within 100 units of one of your cities where one or both cities are older than 2 years have an operative in them")
			return favour_rewards["major_pos"]
		else:
			if len(failures) > 1:
				info.append("<span class='neg'>Major:</span> The following foreign cities do not have operatives in them: %s and %s" % (", ".join(failures[0:-1]), failures[-1]))
			else:
				info.append("<span class='neg'>Major:</span> The foreign city of %s does not have an operative in it" % (failures[0]))
			return favour_rewards["major_neg"]
예제 #10
0
	def negative():
		team_dict_c			= the_world.teams()
		city_dict_c			= the_world.cities()
		operatives_dict_c	= the_world.operatives()
		
		the_world.operatives_in_city(0)
		operatives_by_city	= the_world._operatives_in_city
		
		# First we want a list of all our cities
		our_city_list = []
		their_city_list = []
		
		failures = []
		for city_id, the_city in city_dict_c.items():
			if the_city.dead > 0: continue
			
			if the_city.team == the_team.id:
				our_city_list.append(city_id)
			elif common.current_turn() - the_city.founded > 2:
				their_city_list.append(city_id)
		
		# New we compare each with each
		for our_city_id in our_city_list:
			our_city = city_dict_c[our_city_id]
			
			for their_city_id in their_city_list:
				their_city = city_dict_c[their_city_id]
				
				# Is this city within range?
				distance = path_f.pythagoras((our_city.x, our_city.y), (their_city.x, their_city.y))
				
				if distance <= 100:
					# Check for operative
					if their_city_id in operatives_by_city:
						city_has_op = False
						for o in operatives_by_city[their_city_id]:
							if operatives_dict_c[o].team == the_team.id and operatives_dict_c[o].died < 1:
								city_has_op = True
						
						if not city_has_op:
							failures.append(their_city.name)
					else:
						failures.append(their_city.name)
		
		if len(failures) < 1:
			info.append("<span class='pos'>Negative:</span> All cities older than 2 years and within 100 units of one of your cities have an operative in them")
			return favour_rewards["negative_pos"]
		else:
			if len(failures) > 1:
				info.append("<span class='neg'>Negative:</span> The following foreign cities do not have operatives in them: %s and %s" % (", ".join(failures[0:-1]), failures[-1]))
			else:
				info.append("<span class='neg'>Negative:</span> The foreign city of %s does not have an operative in it" % (failures[0]))
			return favour_rewards["negative_neg"]
예제 #11
0
	def minor():
		city_dict		= the_world.cities()
		team_dict		= the_world.teams()
		deities_lookup	= the_world.deities_lookup()
		
		city_success = False
		for k, our_city in city_dict.items():
			if city_success: continue
			
			self_success = 0
			
			# We only want to use our own cities thanks, nor will we use our dead cities for this test
			if our_city.team != the_team.id: continue
			if our_city.dead: continue
			
			for k, their_city in city_dict.items():
				if city_success: continue# This one has passed already
				
				# If they don't follow P&C we don't care
				if deities_lookup['Phraela and Caist'] not in team_dict[their_city.team].get_deities(the_world.cursor):
					continue
				
				if their_city.dead: continue# Ignore dead cities
				
				distance = path_f.pythagoras((our_city.x, our_city.y), (their_city.x, their_city.y))
				
				# Success?
				if distance < 150:
					if their_city.team == the_team.id:
						# It's us, we need at least 3 in total
						self_success += 1
						if self_success >= 3: city_success = True
					else:
						# It's an ally, outright success
						city_success = True
		
		if city_success:
			info.append("<span class='pos'>Minor:</span> One or more of your cities are within 150 map units of another Phraela and Caist follower's city or 3 of your own cities")
			return favour_rewards["minor_pos"]
		else:
			info.append("<span class='neg'>Minor:</span> None of your cities are within 150 map units of another Phraela and Caist follower's city nor 3 of your own cities")
			return favour_rewards["minor_neg"]
예제 #12
0
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))
예제 #13
0
	def negative():
		team_dict		= the_world.teams()
		deities_lookup	= the_world.deities_lookup()
		city_dict		= the_world.cities()
		
		failures = []
		failure_details = {}
		for city_id_1, the_city_1 in city_dict.items():
			if the_city_1.team != the_team.id or the_city_1.dead == True: continue
			
			failure_details[the_city_1.name] = ''
			pac_range	= 9999999
			other_range	= 9999999
			
			for city_id_2, the_city_2 in city_dict.items():
				if the_city_2.dead == True or city_id_2 == city_id_1: continue
				
				distance = path_f.pythagoras((the_city_1.x, the_city_1.y), (the_city_2.x, the_city_2.y))
				
				if deities_lookup['Phraela and Caist'] in team_dict[the_city_2.team].get_deities(the_world.cursor):
					pac_range = min(pac_range, distance)
				else:
					if other_range > distance:
						failure_details[the_city_1.name] = the_city_2.name
						other_range = min(other_range, distance)
			
			if other_range < pac_range:
				# print the_city_1.name, " - ", failure_details[the_city_1.name], "<br />"
				failures.append(the_city_1.name)
		
		if len(failures) < 1:
			info.append("<span class='pos'>Negative:</span> All of your cities are closer to one that follows Phraela and Caist than to one that does not")
			return favour_rewards["negative_pos"]
		else:
			if len(failures) > 1:
				info.append("<span class='neg'>Negative:</span> The following cities closer to a city that does not follow Phraela and Caist than one that does: %s and %s" % (", ".join(failures[0:-1]), failures[-1]))
			else:
				info.append("<span class='neg'>Negative:</span> The city of %s is closer to a city that does not follow Phraela and Caist than to one that does" % (failures[0]))
			return favour_rewards["negative_neg"]
예제 #14
0
파일: founding_o.py 프로젝트: Teifion/Rob3
def prospective_founding_order(the_line, groups, debug=False):
	results = founding_order(the_line, groups, debug)
	if not the_line.block.msn_order:
		return order_block.fail(results, "Command not valid in live mode")
	
	results['queries'] = []
	results['cost'] = ""
	
	if results['success']:
		# X and Y
		x, y = groups['location'].split(',')
		x = int(x.strip())
		y = int(y.strip())
		
		# Header
		results['results'] = ["[b]Founded '%s' successfully[/b]" % groups['city_name']]
		
		# Terrain
		terrain = mapper_q.get_terrain(the_line.the_world.cursor, x, y)
		results['results'].append("Terrain: %s" % map_data.terrain[terrain].title())
		
		# Supplies
		supplies = []
		icon_size = map_data.map_image_size(int(groups['size']))/4
		for r, rx, ry in map_resources.data_list:
			dist = path_f.pythagoras((rx, ry), (x, y))
			if dist < icon_size:
				supplies.append(r)
		
		if len(supplies) > 1:
			results['results'].append("Supplies: %s" % ", ".join([resource_list.data_dict[s].name for s in supplies]))
		elif len(supplies) == 1:
			results['results'].append("Supply: %s" % ", ".join([resource_list.data_dict[s].name for s in supplies]))
		
		return results
	else:
		return results
예제 #15
0
파일: mapper_f.py 프로젝트: Teifion/Rob3
def team_influence(the_world, team_id):
	"""Returns a list of tiles that the team has influence on and by how much"""
	city_dict = the_world.cities()
	team_dict = the_world.teams()
	
	terrain_tuples = mapper_q.get_all_terrain(the_world.cursor)
	
	tile_control = {}
	
	# First pass, we're only using our cities
	for k, c in city_dict.items():
		if c.dead > 0 or c.secret == 1: continue
		if c.team != team_id: continue
		
		city_loc = mod_ten_tuple((c.x, c.y))
		min_x = city_loc[0]-50
		max_x = city_loc[0]+50
		
		min_y = city_loc[1]-50
		max_y = city_loc[1]+50
		
		for x in range(min_x, max_x, 10):
			for y in range(min_y, max_y, 10):
				tile_loc = (x,y)
				
				# Ignore water
				if tile_loc not in terrain_tuples: continue
				
				tile_range = path_f.pythagoras(city_loc, tile_loc)
				
				if (x,y) not in tile_control:
					tile_control[(x,y)] = 0
				
				tile_control[(x, y)] += city_rules.city_control(tile_range, c, team_dict)
	
	# Second pass, reduce it
	for k, c in city_dict.items():
		if c.dead or c.secret == 1: continue
		if team_dict[c.team].active == 0: continue
		if c.team == team_id: continue
		
		city_loc = mod_ten_tuple((c.x, c.y))
		min_x = city_loc[0]-50
		max_x = city_loc[0]+50
		
		min_y = city_loc[1]-50
		max_y = city_loc[1]+50
		
		for x in range(min_x, max_x, 10):
			for y in range(min_y, max_y, 10):
				tile_loc = (x,y)
				
				# Ignore water
				if tile_loc not in tile_control: continue
				if terrain_tuples[tile_loc] == 0: continue
				
				tile_range = path_f.pythagoras(city_loc, tile_loc)
				tile_control[(x, y)] -= city_rules.city_control(tile_range, c, team_dict)
	
	
	# # Output for a map link
	# output_list = []
	# remove_list = []
	# for k, v in tile_control.items():
	# 	if v > 0.5:
	# 		output_list.append("(%s,%s,%s)" % (k[0], k[1], int(v)))
	# 	else:
	# 		remove_list.append(k)
	# 
	# for r in remove_list:
	# 	del(tile_control[r])
	# 
	# print '<a href="value_map?list=%s">Map</a>' % (":".join(output_list))
	
	return tile_control#, output_list
# 
# def total_influence():
# 	"""Returns a list of tiles that the team has influence on and by how much
# 	it will probably take a while to run"""
# 	city_dict = city.get_city_dict()
# 	team_dict = data.team.get_teams_dict_c()
# 	
# 	terrain_tuples = data.mapper.terrain_tuples()
# 	
# 	tile_control = {}
# 	
# 	# For each city, look at what land they control
# 	for k, c in city_dict.items():
# 		if c.dead or c.secret == 1: continue
# 		if team_dict[c.team].active == 0: continue# Note that IRs affect land control
# 		
# 		# Debug skip stuff
# 		if c.team in [104]:# Skip Seraphim
# 			continue
# 		
# 		city_loc = mod_ten_tuple((c.x, c.y))
# 		min_x = city_loc[0]-rules.city_rules.control_range
# 		max_x = city_loc[0]+rules.city_rules.control_range
# 		
# 		min_y = city_loc[1]-rules.city_rules.control_range
# 		max_y = city_loc[1]+rules.city_rules.control_range
# 		
# 		city_continent = get_tile_continent(city_loc)
# 		# if city_continent < 1: continue
# 		
# 		for x in range(min_x, max_x, 10):
# 			for y in range(min_y, max_y, 10):
# 				tile_loc = (x,y)
# 				
# 				# Ignore water
# 				if tile_loc not in terrain_tuples: continue
# 				if terrain_tuples[tile_loc] == 0: continue
# 				
# 				# Can't control stuff on other continents
# 				tile_continent = get_tile_continent(tile_loc)
# 				if tile_continent != city_continent: continue
# 				
# 				# Default value if it doesn't exist yet
# 				if (x,y) not in tile_control: tile_control[(x,y)] = {}
# 				
# 				tile_range = data.path.pythagoras(city_loc, tile_loc)
# 				control = rules.city_rules.city_control(tile_range, c)
# 				
# 				if control <= 0: continue
# 				
# 				if c.team not in tile_control[(x,y)]:
# 					tile_control[(x,y)][c.team] = 0
# 				tile_control[(x,y)][c.team] += control
# 	
# 	return tile_control
# 
# 
# def new_continent(name, x, y):
# 	query = """INSERT INTO map_continents (name, x, y)
# 		values
# 		('%s', %s, %s);""" % (database.escape(name), x, y)
# 	try: database.cursor.execute(query)
# 	except Exception as e:
# 		raise Exception("Database error: %s\nQuery: %s" % (str(e.args[0]).replace("\n",""), query))
예제 #16
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))
예제 #17
0
파일: ti_f.py 프로젝트: Teifion/Rob3
def armies(cursor, the_world, the_team):
	output = []
	unit_dict = the_world.units()#(the_team.id)
	army_dict = the_world.armies_from_team(the_team.id)
	city_dict = the_world.cities()
	monster_dict = the_world.monsters()
	
	output.append('''<div class="ti_section" id="armies_div">
	<table border="0" cellspacing="0" cellpadding="5" style="width:100%%;">
		<tr class="row2">
			<th>Army</th>
			<th>Location</th>
			<th>Size</th>
			<th>&nbsp;</th>
		</tr>''')
	
	count = -1
	for a, the_army in army_dict.items():
		count+=1
		
		if the_army.garrison < 1:
			# First lets see if the city is dead...
			
			# Default
			army_location = str((int(the_army.x), int(the_army.y)))
			
			# Now to see if it's near something
			min_dist = 9999
			for c, the_city in city_dict.items():
				if the_city.dead == True: continue
				distance = path_f.pythagoras((the_army.x, the_army.y), (the_city.x, the_city.y))
				
				if distance < 150 and distance < min_dist:
					army_location = "%s, near %s" % (str((int(the_army.x), int(the_army.y))), the_city.name)
					min_dist = distance
				
		else:
			if the_army.garrison not in city_dict: continue# Skip dead cities
			if city_dict[the_army.garrison].dead == True: continue
			army_location = "Garrison"
		
		output.append("""
		<tr class="row%(row)s">
			<td>%(name)s</td>
			<td>%(army_location)s</td>
			<td>%(army_size)s</td>
			<td style="padding: 0px;">
				<a href="#" id="army_%(army_id)s_squad_show" onclick="$('#army_%(army_id)s_squad_show').hide(); $('#army_%(army_id)s_squads').show(); $('#army_%(army_id)s_squad_hide').show(); return false;" class="block_link">Show squads</a>
				<a href="#" id="army_%(army_id)s_squad_hide" onclick="$('#army_%(army_id)s_squad_show').show(); $('#army_%(army_id)s_squads').hide(); $('#army_%(army_id)s_squad_hide').hide(); return false;" class="block_link" style="display: none;">Hide squads</a>
			</td>
		</tr>""" % {
				"row":				count%2,
				"name":		the_army.name,
				"army_id":			the_army.id,
				
				"army_location":	army_location,
				"army_size":		the_army.get_size(cursor),
			})
		
		# Army squads
		output.append("<tr id='army_%s_squads' style='display: none;'><td style='padding: 5px 20px 10px;' colspan='4'>" % the_army.id)
		
		output.append("""
			<table border="0" cellspacing="0" cellpadding="5" style="width:100%%;">
				<tr class="row2">
					<th>Squad</th>
					<th>Type</th>
					<th>Size</th>
					<!--<th>Experience</th>-->
				</tr>""")
		
		count2 = -1
		# Squads
		for s, the_squad in the_army.squads.items():
			if the_squad.unit not in unit_dict:
				continue
			
			count2 += 1
			output.append("""
			<tr class="row%(count)s">
				<td>%(name)s</td>
				<td>%(squad_type)s</td>
				<td>%(squad_size)s</td>
			</tr>""" % {
				"count":		count2%2,
				"name":	the_squad.name,
				"squad_type":	unit_dict[the_squad.unit].name,
				"squad_size":	the_squad.amount,
				"squad_id":		the_squad.id
			})
		
		# Monsters
		for monster_id, amount in the_army.monsters.items():
			if amount < 1: continue
			the_monster = monster_dict[monster_id]
			
			count2 += 1
			output.append("""
			<tr class="row{count}">
				<td>{name}</td>
				<td><em>Monster</em></td>
				<td>{amount}</td>
			</tr>""".format(
				count	= count2 % 2,
				name	= the_monster.name,
				amount	= amount,
			))
		
		output.append("</table>")
	
	output.append('</table></div>')
	return "".join(output)