def get_view_command(self, command): bot = self.get_bot_from_command(command) bot_position = bot.position if type(command) == commands.Attack: nodes = self.graph.nodes() total_mass = 0.0 first_position = regressions2.get_node_vector(self, nodes[0]) first_mass = self.graph.node[nodes[0]]["p_enemy"] * 1 / ( bot_position.distance(first_position)**2 + 1) center = first_position * first_mass total_mass += first_mass for node_index in nodes[1:]: prob = self.graph.node[node_index]["p_enemy"] node_position = regressions2.get_node_vector(self, node_index) distance = bot_position.distance(node_position) mass = 1 / ((distance)**2 + 1) * prob #Prevent very close, low probability enemies from biasing. ## if prob < .2 and distance < 8: ## continue center += node_position * mass total_mass += mass if total_mass != 0.0: final_vector = center / total_mass else: final_vector = command.target[-1] command.lookAt = final_vector #TODO weight direction of travel into vector? return command
def get_view_command(self, command): bot = self.get_bot_from_command(command) bot_position = bot.position if type(command) == commands.Attack: nodes = self.graph.nodes() total_mass = 0.0 first_position = regressions2.get_node_vector(self, nodes[0]) first_mass = self.graph.node[nodes[0]]["p_enemy"] * 1/(bot_position.distance(first_position)**2+1) center = first_position * first_mass total_mass += first_mass for node_index in nodes[1:]: prob = self.graph.node[node_index]["p_enemy"] node_position = regressions2.get_node_vector(self, node_index) distance = bot_position.distance(node_position) mass = 1/((distance)**2+1) * prob #Prevent very close, low probability enemies from biasing. ## if prob < .2 and distance < 8: ## continue center += node_position * mass total_mass += mass if total_mass != 0.0: final_vector = center/total_mass else: final_vector = command.target[-1] command.lookAt = final_vector #TODO weight direction of travel into vector? return command
def get_chokes(instance, choke_candidates): #prevent writing over base space. used_set = set() start, finish = instance.level.botSpawnAreas[instance.game.enemyTeam.name] for i, j in itertools.product(range(int(start.x), int(finish.x)), range(int(start.y), int(finish.y))): node_index = regressions2.get_node_index(instance, Vector2(i,j)) used_set.add(node_index) choke_dict = {} master_chokes = set() flag_node = regressions2.get_node_index(instance, instance.game.team.flag.position) spawn_node = regressions2.get_node_index(instance, get_enemy_base(instance)) shortest_length = nx.shortest_path_length(instance.graph, source=spawn_node, target=flag_node, weight="choke_covered") choke_count = 0 while shortest_length == 0.0: if len(choke_candidates) == 0.0: print "RAN OUT OF CANDIDATES!" break choke_count += 1 one_choke = set() choke_center = choke_candidates.pop() choke_vector = regressions2.get_node_vector(instance, choke_center) #Ignore potential chokes too far from their spawn. while (choke_vector.distance((get_enemy_base(instance))) > 5.0 or choke_center in used_set) and len(choke_candidates) > 0: choke_vector = regressions2.get_node_vector(instance, choke_center) choke_center = choke_candidates.pop() if len(choke_candidates) == 0: print "RAN OUT OF CANDIDATES!" return choke_dict, master_chokes if choke_vector.distance((get_enemy_base(instance))) > 5.0: print "RAN OUT OF CANDIDATES, LAST CANDIDATE DIDN'T WORK!" return choke_dict, master_chokes one_choke.add(choke_center) for x in range(4): neighbors = set() for node in one_choke: neighbors2 = instance.graph.neighbors(node) if neighbors2 is not None: for neighbor2 in neighbors2: if neighbor2 not in used_set: neighbors.add(neighbor2) one_choke = one_choke.union(neighbors) used_set = used_set.union(one_choke) for node in one_choke: instance.graph.node[node]["choke_covered"] = 1.0 neighbors = instance.graph.neighbors(node) for neighbor in neighbors: instance.graph.edge[node][neighbor]["choke_covered"] = 1.0 choke_dict[choke_center] = { "nodes": one_choke, "redundancy": 0} master_chokes = master_chokes.union(one_choke) shortest_length = nx.shortest_path_length(instance.graph, source=spawn_node, target=flag_node, weight="choke_covered") return choke_dict, master_chokes
def weight_camp_locations_by_sight(instance, close_nodes): #Calculate the weight of all squares close to the enemy base relying on how many of the exit squares can be shot. enemy_base = get_enemy_base(instance) for node_index in close_nodes: node_position = regressions2.get_node_vector(instance, node_index) cells = [] w = visibility.Wave((88, 50), lambda x, y: instance.level.blockHeights[x][y] > 1, lambda x, y: cells.append((x, y))) w.compute(node_position) for x, y in cells: cell_position = Vector2(x, y) cell_node_index = regressions2.get_node_index( instance, cell_position) if node_position.distance( cell_position) < instance.level.firingDistance: #Edges don't work with our functions, and are unlikely to be actual optimum. #TODO fully debug rather than hack. if not (node_position.x < 1.0 or node_position.x > 87.0 or node_position.y < 1.0 or node_position.y > 47.0): camp_value = instance.graph.node[cell_node_index][ "camp_target"] / (cell_position.distance(enemy_base) + 3) instance.graph.node[node_index][ "camp_location"] += camp_value
def get_view_command(self, command): bot = self.game.team.members[int(command.botId[-1])] final_direction = command.target[-1] influence_vector = Vector2(0, 0) total_count = 0.0 for node_index in self.graph.nodes(): p_enemy = self.graph.node[node_index]["p_enemy"] if p_enemy != 0.0: node_vector = regressions2.get_node_vector(self, node_index) influence_vector += node_vector/(node_vector.distance(bot.position)+1)*p_enemy total_count += 1/(node_vector.distance(bot.position)+1)*p_enemy if influence_vector.length() != 0.0: influence_vector /= total_count final_direction = influence_vector if type(command) == commands.Attack: command.lookAt = final_direction elif type(command) == commands.Defend: final_direction = final_direction - bot_position final_direction.normalize() command.facingDirection = final_direction return command
def get_view_command(self, command): bot = self.game.team.members[int(command.botId[-1])] final_direction = command.target[-1] influence_vector = Vector2(0, 0) total_count = 0.0 for node_index in self.graph.nodes(): p_enemy = self.graph.node[node_index]["p_enemy"] if p_enemy != 0.0: node_vector = regressions2.get_node_vector(self, node_index) influence_vector += node_vector / ( node_vector.distance(bot.position) + 1) * p_enemy total_count += 1 / (node_vector.distance(bot.position) + 1) * p_enemy if influence_vector.length() != 0.0: influence_vector /= total_count final_direction = influence_vector if type(command) == commands.Attack: command.lookAt = final_direction elif type(command) == commands.Defend: final_direction = final_direction - bot_position final_direction.normalize() command.facingDirection = final_direction return command
def get_probability(instance, node, last_position, enemy_bot): #Calculates probability of a given bot being in a possible square it could occupy. #Prob based on center enemy_position = last_position node_position = regressions2.get_node_vector(instance, node) distance_vector = enemy_position - node_position probability = distance_vector.length()**2 #Prob based on simple linear extrapolation of path return probability
def extrapolate(instance): points = [] bot_extraps = {} for enemy_bot in instance.enemies.keys(): if enemy_bot.health > 0.0: #Get enemy heading. extrapolation = enemy_bot.position - instance.enemies[enemy_bot] #If we have no new data on enemy location, assume they are heading in direction of flag. #TODO account for pin bots, hunt bots, and defend bots. #TODO account for probable pathing... pheremone? if extrapolation.length() == 0.0: extrapolation = instance.game.team.flag.position - enemy_bot.position if extrapolation.length() == 0.0: extrapolation = instance.game.enemyTeam.flagScoreLocation - enemy_bot.position extrapolation.normalize() #Calculate point enemy should have ran to. TODO make realistic with level speed. #TODO use visualizer to simultaneously show with visualization via circle drawings. enemy_speed = get_enemy_bot_speed(instance, enemy_bot)*.8 #.8 because not straight running lines. #Resolve points going off map by having the bot calculated as at map edge. if extrapolation.x > enemy_bot.position.x: x_bound = 87 else: x_bound = 2 if extrapolation.y > enemy_bot.position.y: y_bound = 49 else: y_bound = 2 if enemy_bot.seenlast != None: extrapolated_change = extrapolation * enemy_speed * (enemy_bot.seenlast + 1.5) else: extrapolated_change = extrapolation * enemy_speed * 1.5 if extrapolated_change.x > abs(enemy_bot.position.x - x_bound): extrapolated_change.x = x_bound if extrapolated_change.y > abs(enemy_bot.position.y - y_bound): extrapolated_change.y = y_bound final_position = enemy_bot.position + extrapolated_change x, y = regressions2.sanitize_position(instance, final_position) final_position = Vector2(x, y) node_index = regressions2.get_node_index(instance, final_position) vector = regressions2.get_node_vector(instance, node_index) points.append(vector) bot_extraps[enemy_bot] = vector if instance.DRAW_POINTS == "extrap": instance.points = points return bot_extraps
def assign_single_node_fs_density(instance, source_node_id, enemy_bot): bot_position = regressions2.get_node_vector(instance, source_node_id) direction = get_direction(instance, enemy_bot) #If the bot is definitely dead (IE hasn't respawned etc...) don't bother filling in data about it. #Get direction returns a direction for just starting bots. if direction == None: return #Get all nodes visible to the hypothetical enemy bot, assign scores to them based on enemy sight and enemy firing capability. simulated_bot = {"position": bot_position, "direction": direction} visible_nodes = regressions2.one_bot_sees(instance, enemy_bot, simulated_bot) #TODO for node_index in visible_nodes: node_position = regressions2.get_node_vector(instance, node_index) #We care if about what probability the enemy is at the source node being evaluated. p_enemy = instance.graph.node[source_node_id]["p_enemy"] p_sight = instance.graph.node[node_index]["p_enemy_sight"] p_fire = instance.graph.node[node_index]["p_enemy_fire"] #TODO make fn to DRY this. #@FIRING #We purposefully overestimate their shooting range to have bots play cautiously. #We are also estimating at time of, which leaves lots of time for commands, hence the cone is not accurate. if (node_position - bot_position).length() < instance.level.firingDistance + 6: if p_fire == 0.0: instance.graph.node[node_index]["p_enemy_fire"] = p_enemy else: p_not_prior_fire = 1.0 - p_fire p_not_current_fire = 1.0 - p_enemy p_neither = p_not_prior_fire * p_not_current_fire final_prob_fire = 1.0 - p_neither instance.graph.node[node_index][ "p_enemy_fire"] = final_prob_fire if p_sight == 0.0: instance.graph.node[node_index]["p_enemy_sight"] = p_enemy else: p_not_prior_sight = 1.0 - p_sight p_not_current_sight = 1.0 - p_enemy p_neither = p_not_prior_sight * p_not_current_sight final_prob_sight = 1.0 - p_neither instance.graph.node[node_index]["p_enemy_sight"] = final_prob_sight
def weight_camp_locations_by_choke_exposure(instance): for node in instance.choke_dict.keys(): enemy_base_square = regressions2.get_node_vector(instance, node) cells = [] w = visibility.Wave((88, 50), lambda x, y: instance.level.blockHeights[x][y] > 1, lambda x, y: cells.append((x,y))) w.compute(enemy_base_square) for x, y in cells: cell_position = Vector2(x, y) cell_node_index = regressions2.get_node_index(instance, cell_position) if cell_position.distance(enemy_base_square) < instance.level.firingDistance + 3: instance.graph.node[cell_node_index]["camp_location"] *= .8
def get_probability(instance, node, last_position, enemy_bot, bot_extraps): #Calculates probability of a given bot being in a possible square it could occupy. #Prob based on center node_position = regressions2.get_node_vector(instance, node) #If we don't have a linear extrap on the enemy, calc random outward radiating ring. if enemy_bot not in bot_extraps.keys(): distance_vector = enemy_bot.position - node_position probability = distance_vector.length()**2.0 else: probability = 1.0/(node_position.distance(bot_extraps[enemy_bot])**2.0+1) #Prob based on simple linear extrapolation of path return probability
def assign_single_node_fs_density(instance, source_node_id, enemy_bot): bot_position = regressions2.get_node_vector(instance, source_node_id) direction = get_direction(instance, enemy_bot) #If the bot is definitely dead (IE hasn't respawned etc...) don't bother filling in data about it. #Get direction returns a direction for just starting bots. if direction == None: return #Get all nodes visible to the hypothetical enemy bot, assign scores to them based on enemy sight and enemy firing capability. simulated_bot = {"position": bot_position, "direction" : direction} visible_nodes = regressions2.one_bot_sees(instance, enemy_bot, simulated_bot) #TODO for node_index in visible_nodes: node_position = regressions2.get_node_vector(instance, node_index) #We care if about what probability the enemy is at the source node being evaluated. p_enemy = instance.graph.node[source_node_id]["p_enemy"] p_sight = instance.graph.node[node_index]["p_enemy_sight"] p_fire = instance.graph.node[node_index]["p_enemy_fire"] #TODO make fn to DRY this. #@FIRING #We purposefully overestimate their shooting range to have bots play cautiously. #We are also estimating at time of, which leaves lots of time for commands, hence the cone is not accurate. if (node_position - bot_position).length() < instance.level.firingDistance + 6: if p_fire == 0.0: instance.graph.node[node_index]["p_enemy_fire"] = p_enemy else: p_not_prior_fire = 1.0 - p_fire p_not_current_fire = 1.0 - p_enemy p_neither = p_not_prior_fire * p_not_current_fire final_prob_fire = 1.0 - p_neither instance.graph.node[node_index]["p_enemy_fire"] = final_prob_fire if p_sight == 0.0: instance.graph.node[node_index]["p_enemy_sight"] = p_enemy else: p_not_prior_sight = 1.0 - p_sight p_not_current_sight = 1.0 - p_enemy p_neither = p_not_prior_sight * p_not_current_sight final_prob_sight = 1.0 - p_neither instance.graph.node[node_index]["p_enemy_sight"] = final_prob_sight
def produce_best_camp_locations(instance, close_nodes): #Return best camping destinations to commander for use in action picking. camp_destinations = [] for node in close_nodes: pair = (instance.graph.node[node]["camp_location"], node) camp_destinations.append(pair) camp_destinations.sort() camp_nodes = [] for score, node in camp_destinations: camp_nodes.append(node) return_positions = [] #Remove all nodes connected by 5 or less. for x in range(10): if len(camp_nodes) == 0: break node = camp_nodes.pop() neighbors = instance.graph.neighbors(node) for neighbor_node in neighbors: neighbors2 = instance.graph.neighbors(neighbor_node) for neighbor2 in neighbors2: neighbors3 = instance.graph.neighbors(neighbor2) for neighbor3 in neighbors3: neighbors4 = instance.graph.neighbors(neighbor3) for neighbor4 in neighbors4: neighbors5 = instance.graph.neighbors(neighbor4) for neighbor5 in neighbors5: try: camp_nodes.remove(neighbor5) except ValueError: pass try: camp_nodes.remove(neighbor4) except ValueError: pass try: camp_nodes.remove(neighbor3) except ValueError: pass try: camp_nodes.remove(neighbor2) except ValueError: pass try: camp_nodes.remove(neighbor_node) except ValueError: pass return_positions.append(regressions2.get_node_vector(instance, node)) if instance.DRAW_POINTS == "camp": instance.points = return_positions return return_positions
def weight_camp_locations_by_choke_exposure(instance): for node in instance.choke_dict.keys(): enemy_base_square = regressions2.get_node_vector(instance, node) cells = [] w = visibility.Wave((88, 50), lambda x, y: instance.level.blockHeights[x][y] > 1, lambda x, y: cells.append((x, y))) w.compute(enemy_base_square) for x, y in cells: cell_position = Vector2(x, y) cell_node_index = regressions2.get_node_index( instance, cell_position) if cell_position.distance( enemy_base_square) < instance.level.firingDistance + 3: instance.graph.node[cell_node_index]["camp_location"] *= .8
def weight_camp_locations_by_sight(instance, close_nodes): #Calculate the weight of all squares close to the enemy base relying on how many of the exit squares can be shot. enemy_base = get_enemy_base(instance) for node_index in close_nodes: node_position = regressions2.get_node_vector(instance, node_index) cells = [] w = visibility.Wave((88, 50), lambda x, y: instance.level.blockHeights[x][y] > 1, lambda x, y: cells.append((x,y))) w.compute(node_position) for x, y in cells: cell_position = Vector2(x, y) cell_node_index = regressions2.get_node_index(instance, cell_position) if node_position.distance(cell_position) < instance.level.firingDistance: #Edges don't work with our functions, and are unlikely to be actual optimum. #TODO fully debug rather than hack. if not (node_position.x < 1.0 or node_position.x > 87.0 or node_position.y < 1.0 or node_position.y > 47.0): camp_value = instance.graph.node[cell_node_index]["camp_target"]/(cell_position.distance(enemy_base)+3) instance.graph.node[node_index]["camp_location"] += camp_value
def get_chokes(instance, choke_candidates): #prevent writing over base space. used_set = set() start, finish = instance.level.botSpawnAreas[instance.game.enemyTeam.name] for i, j in itertools.product(range(int(start.x), int(finish.x)), range(int(start.y), int(finish.y))): node_index = regressions2.get_node_index(instance, Vector2(i, j)) used_set.add(node_index) choke_dict = {} master_chokes = set() flag_node = regressions2.get_node_index(instance, instance.game.team.flag.position) spawn_node = regressions2.get_node_index(instance, get_enemy_base(instance)) shortest_length = nx.shortest_path_length(instance.graph, source=spawn_node, target=flag_node, weight="choke_covered") choke_count = 0 while shortest_length == 0.0: if len(choke_candidates) == 0.0: print "RAN OUT OF CANDIDATES!" break choke_count += 1 one_choke = set() choke_center = choke_candidates.pop() choke_vector = regressions2.get_node_vector(instance, choke_center) #Ignore potential chokes too far from their spawn. while (choke_vector.distance((get_enemy_base(instance))) > 5.0 or choke_center in used_set) and len(choke_candidates) > 0: choke_vector = regressions2.get_node_vector(instance, choke_center) choke_center = choke_candidates.pop() if len(choke_candidates) == 0: print "RAN OUT OF CANDIDATES!" return choke_dict, master_chokes if choke_vector.distance((get_enemy_base(instance))) > 5.0: print "RAN OUT OF CANDIDATES, LAST CANDIDATE DIDN'T WORK!" return choke_dict, master_chokes one_choke.add(choke_center) for x in range(4): neighbors = set() for node in one_choke: neighbors2 = instance.graph.neighbors(node) if neighbors2 is not None: for neighbor2 in neighbors2: if neighbor2 not in used_set: neighbors.add(neighbor2) one_choke = one_choke.union(neighbors) used_set = used_set.union(one_choke) for node in one_choke: instance.graph.node[node]["choke_covered"] = 1.0 neighbors = instance.graph.neighbors(node) for neighbor in neighbors: instance.graph.edge[node][neighbor]["choke_covered"] = 1.0 choke_dict[choke_center] = {"nodes": one_choke, "redundancy": 0} master_chokes = master_chokes.union(one_choke) shortest_length = nx.shortest_path_length(instance.graph, source=spawn_node, target=flag_node, weight="choke_covered") return choke_dict, master_chokes