def _position_get_neighbours(self, world): neighbours = [ Position(x=self.x - 1, y=self.y), Position(x=self.x + 1, y=self.y), Position(x=self.x, y=self.y - 1), Position(x=self.x, y=self.y + 1) ] valid_neighbours = [] for neighbour in neighbours: if 0 <= neighbour.x < world.width and 0 <= neighbour.y < world.height: valid_neighbours.append(neighbour) return valid_neighbours
def seventh_police_strategy(self, agent: Police): # Let's find a path from agent's position to one of its circulating areas: g = Graph(self.world, (agent.position.y, agent.position.x), self._calculate_black_pos(agent)) _index = self.police_circulate_index[agent.id] dest = self.police_circulating_areas[agent.id][_index] # Iterating from start to end, then from end to start. if _index in [0, len(self.police_circulating_areas[agent.id]) - 1]: self.police_circulate_iter[agent.id] *= -1 if len(self.police_circulating_areas[agent.id]) > 1: self.police_circulate_index[ agent.id] += self.police_circulate_iter[agent.id] self.print("Source : (%d, %d)" % (agent.position.y, agent.position.x)) self.print("Destination : (%d, %d)" % (dest[1], dest[2])) path = g.bfs((dest[1], dest[2]), False) if path is None: return False self.path3[agent.id] = path self.print(self.path3[agent.id]) if self.path3[agent.id]: if self._move( agent.id, Position(self.path3[agent.id][0][1], self.path3[agent.id][0][0]), agent.position): self.path3[agent.id].pop(0) return True else: del self.path3[agent.id] else: del self.path3[agent.id] return False
def police_move(self, police, target): id = police.id for p in self.world.polices: if p.id == id: police = p pos = police.position # print("police {} from ({} , {}) is going to ({} , {})".format(police.id, pos.x, pos.y, target.x, target.y)) dist = self.find_dist(pos, target) polices_pos = [(p.position.x, p.position.y) for p in self.world.polices] node = Position(pos.x, pos.y + 1) nodetup = (node.x,node.y) if self.check_empty_node(node) and not self.is_bomb(node) and nodetup not in polices_pos and self.find_dist(node, target) + 1 == dist: # print(police.id, "Down" ,self.find_dist(node, target) , "<" ,dist , self.check_empty_node(node) , (node.x , node.y)) self.move(police.id, ECommandDirection.Down) return node = Position(pos.x + 1, pos.y) nodetup = (node.x, node.y) if self.check_empty_node(node) and not self.is_bomb(node) and nodetup not in polices_pos and self.find_dist(node, target) + 1 == dist: # print(police.id, "Right" ,self.find_dist(node, target) , "<" ,dist , self.check_empty_node(node) , (node.x , node.y)) self.move(police.id, ECommandDirection.Right) return node = Position(pos.x, pos.y - 1) nodetup = (node.x, node.y) if self.check_empty_node(node) and not self.is_bomb(node) and nodetup not in polices_pos and self.find_dist(node, target) + 1 == dist: # print(police.id, "Up" ,self.find_dist(node, target) , "<" ,dist , self.check_empty_node(node) , (node.x , node.y)) self.move(police.id, ECommandDirection.Up) return node = Position(pos.x - 1, pos.y) nodetup = (node.x, node.y) if self.check_empty_node(node) and not self.is_bomb(node) and nodetup not in polices_pos and self.find_dist(node, target) + 1 == dist: # print(police.id, "Left" ,self.find_dist(node, target) , "<" ,dist , self.check_empty_node(node) , (node.x , node.y)) self.move(police.id, ECommandDirection.Left) return
def second_police_strategy(self, agent: Police): # Let's continue the path: if agent.id in self.path: # Walk to bomb or defuse it if self.path[agent.id]: if self._move( agent.id, Position(self.path[agent.id][0][1], self.path[agent.id][0][0]), agent.position): self.path[agent.id].pop(0) else: del self.path[agent.id] return False else: bomb = self.police_bomb_site[agent.id] del self.path[agent.id] if not self._defuse(agent.id, Position(bomb[1], bomb[0]), agent.position): return False return True return False
def fifth_terrorist_strategy(self, agent: Terrorist): dest = self._terrorist_destination(agent) if dest: g = Graph(self.world, (agent.position.y, agent.position.x), self._calculate_black_pos(agent)) path = g.bfs(dest) if path: # Move! if self._move(agent.id, Position(path[0][1], path[0][0]), agent.position): path.pop(0) self.path[agent.id] = path return True else: # Hey terrorist, you are adjacent to a bombsite... Hurry up and plant! del self.terrorist_bomb_site[agent.id] if self._plant(agent.id, Position(dest[1], dest[0]), agent.position): return True # Your way is closed:) please wait. return False
def fifth_police_strategy(self, agent: Police): # Using an extreme police power, sound board! sounds = self.sound_board[agent.position.y][agent.position.x] # Collecting exact location of a bombsite for a possible hearing sound from agent's position: site_pos, dest = [None, None, None], None for sound in sounds: if sound[0] == ESoundIntensity.Strong: site_pos[0] = sound[1], sound[2] elif sound[0] == ESoundIntensity.Normal: site_pos[1] = sound[1], sound[2] elif sound[0] == ESoundIntensity.Weak: site_pos[2] = sound[1], sound[2] # Listening to server for a sound with priority of strong, normal and week... if site_pos[0] and ESoundIntensity.Strong in agent.bomb_sounds: self.print("Strong sound bomb found: (%d, %d)" % (site_pos[0][0], site_pos[0][1])) dest = site_pos[0] elif site_pos[1] and ESoundIntensity.Normal in agent.bomb_sounds: self.print("Normal sound bomb found: (%d, %d)" % (site_pos[1][0], site_pos[1][1])) dest = site_pos[1] ''' elif site_pos[2] and ESoundIntensity.Weak in agent.bomb_sounds: self.print("Weak sound bomb found: (%d, %d)" %(site_pos[2][0], site_pos[2][1])) dest = site_pos[2] ''' # Checking that exact destination of a planted bomb is found! if dest is None or dest in self.police_defusing_site.values(): return False # Let's go and defuseeee :)) g = Graph(self.world, (agent.position.y, agent.position.x), self._calculate_black_pos(agent)) path = g.bfs(dest, False) if path is None: return False self.path2[agent.id] = path self.police_defusing_site[agent.id] = dest if self.path2[agent.id]: if self._move( agent.id, Position(self.path2[agent.id][0][1], self.path2[agent.id][0][0]), agent.position): self.path2[agent.id].pop(0) else: del self.path2[agent.id] return False else: del self.path2[agent.id] return False if agent.id in self.path3: del self.path3[agent.id] return True
def third_police_strategy(self, agent: Police): # Check each police vision to detect a bomb defusion: if self.world.bombs: for bomb in self.world.bombs: if bomb.defuser_id != -1 or ( (bomb.position.y, bomb.position.x) in self.police_defusing_site.values() and (agent.id not in self.police_defusing_site or self.police_defusing_site[agent.id] != (bomb.position.y, bomb.position.x))): continue distance = AI._distance(agent.position, bomb.position) if distance <= self.world.constants.police_vision_distance: # Checking wether bomb is going to explode when police arrives g = Graph(self.world, (agent.position.y, agent.position.x), self._calculate_black_pos(agent)) path = g.bfs((bomb.position.y, bomb.position.x)) if path is None: return True if agent.id in self.path2: del self.path2[agent.id] if agent.id in self.path3: del self.path3[agent.id] self.police_bomb_site[agent.id] = (bomb.position.y, bomb.position.x) self.path[agent.id] = path self.police_defusing_site[agent.id] = (bomb.position.y, bomb.position.x) if len( self.path[agent.id] ) * 0.5 + self.world.constants.bomb_defusion_time <= bomb.explosion_remaining_time: # Walk to bomb or defuse it if self.path[agent.id]: if self._move( agent.id, Position(self.path[agent.id][0][1], self.path[agent.id][0][0]), agent.position): self.path[agent.id].pop(0) else: del self.path[agent.id] else: if self._defuse(agent.id, bomb.position, agent.position): del self.path[agent.id] else: del self.path[agent.id] # Wether police can defuse the bomb or not True can keep the police safe(hold for some cycles) from a path2 leading to the bomb! return True return False
def fourth_police_strategy(self, agent: Police): # Let's continue the path2: if agent.id in self.path2: if self.path2[agent.id]: if self._move( agent.id, Position(self.path2[agent.id][0][1], self.path2[agent.id][0][0]), agent.position): self.path2[agent.id].pop(0) return True else: del self.path2[agent.id] else: del self.path2[agent.id] return False
def fourth_terrorist_strategy(self, agent: Terrorist): # Continue to your path or plant a bomb if agent.id in self.path: if self.path[agent.id]: path = self.path[agent.id] if self._move(agent.id, Position(path[0][1], path[0][0]), agent.position): self.print("Agent %d is moving: (%d, %d) --> (%d, %d)" % (agent.id, agent.position.y, agent.position.x, path[0][0], path[0][1])) path.pop(0) return True else: del self.path[agent.id] else: # Hey terrorist, you are adjacent to a bombsite... Hurry up and plant! dest = self.terrorist_bomb_site[agent.id] del self.terrorist_bomb_site[agent.id] del self.path[agent.id] if self._plant(agent.id, Position(dest[1], dest[0]), agent.position): self.print("Agent %d is planting a bomb!" % agent.id) return True return False
def sixth_police_strategy(self, agent: Police): if agent.id in self.police_defusing_site: del self.police_defusing_site[agent.id] # Let's continue the path3: if agent.id in self.path3: if not self.path3[agent.id]: del self.path3[agent.id] return False if self._move( agent.id, Position(self.path3[agent.id][0][1], self.path3[agent.id][0][0]), agent.position): self.path3[agent.id].pop(0) return True else: del self.path3[agent.id] return False
def get_sorted_bombs_list(self, source, number, checked = set() , verifiedBobms = None): # finds nearest bombs from the source position bombs_list = [] # [position] if verifiedBobms is not None: verifiedBobms = {(b.x,b.y) for b in verifiedBobms} Q = queue.Queue() Q.put(source) adjs = [[0, -1], [0, +1], [-1, 0], [+1, 0]] while not Q.empty() and len(bombs_list) < number: node = Q.get() # bfs is checking for bombs from the source to board edges ... if (node.x, node.y) in checked: continue checked.add((node.x, node.y)) if verifiedBobms is not None: if (node.x, node.y) in verifiedBobms: bombs_list.append(node) if (node.x, node.y) != (source.x, source.y): continue elif self.is_bomb(node): bombs_list.append(node) if (node.x, node.y) != (source.x, source.y): continue # cause we cant see pass the bomb so we dont see its adjs for adj in adjs: new_node = Position(x=node.x + adj[0], y=node.y + adj[1]) if self.check_empty_node(new_node): Q.put(new_node) return bombs_list
def find_dist(self, policePos, bombPos): posQ = queue.Queue() posQ.put(policePos) distQ = queue.Queue() distQ.put(0) checked = set() adjs = [[ 0,-1], [ 0,+1], [-1, 0], [+1, 0]] policesPos = [(police.position.x, police.position.y) for police in self.world.polices] while not posQ.empty(): node = posQ.get() dist = distQ.get() if (node.x, node.y) in checked: continue if (node.x, node.y) in policesPos and (node.x, node.y) != (policePos.x, policePos.y) : continue checked.add((node.x, node.y)) for adj in adjs: new_node = Position(x=node.x + adj[0], y=node.y + adj[1]) if (new_node.x, new_node.y) == (bombPos.x, bombPos.y): return dist + 1 elif self.check_empty_node(new_node) and not self.is_bomb(new_node): posQ.put(new_node) distQ.put(dist + 1) # print("could find a way ...100000") return 100000
def decide(self): start = time.time() print('decide' + ' ' + str(self.current_cycle)) if self.my_side == 'Police': my_agents = self.world.polices # return 0 else: my_agents = self.world.terrorists # ignore dead agents alive_agents = [] for agent in my_agents: if agent.status == EAgentStatus.Dead: if self.my_side == 'Terrorist': if self.target_bombsites[agent.id]: if self.target_bombsites[agent.id] in self.bombsites: self.bombsites[self.target_bombsites[agent.id]]['task'] = 0 self.bombsites[self.target_bombsites[agent.id]]['status'] = -1 self.target_bombsites[agent.id] = None else: alive_agents.append(agent) # update bombsites if terrorists score is changed: exploded_bombsites = [] if self.last_scores['Terrorist'] != self.world.scores['Terrorist']: for bombsite in self.bombsites: if self.world.board[bombsite[0]][bombsite[1]] == ECell.Empty: exploded_bombsites.append(bombsite) for bombsite in exploded_bombsites: del self.bombsites[bombsite] if exploded_bombsites: print(exploded_bombsites) updated,unreachables,bypassed_bombsites_list = False, [], [] for i,bombsite in enumerate(self.unreachable_bombsites): distance, path, bypassed_bombsites = self._a_star(self.start_pos,bombsite,agent_block=False,bombsite_block=False) if not bypassed_bombsites: self.bombsites[bombsite] = {'size':self.world.board[bombsite[0]][bombsite[1]],'initial_distance':distance, 'status':-2,'task':0,'bscore':0, 'failed':0, 'agent':None,'ert':-1} updated = True print('unreachable opened:',bombsite,self.bombsites[bombsite]) else: unreachables.append(bombsite) bypassed_bombsites_list.append((bombsite,bypassed_bombsites)) self.unreachable_bombsites = unreachables if updated: for bombsite in self.bombsites: self.bombsites[bombsite]['bscore'] = 0 for bombsite, bypassed_bombsites in bypassed_bombsites_list: bypassed_bombsite = bypassed_bombsites[-1] unreachable_size = self.world.board[bombsite[0]][bombsite[1]] self.bombsites[bypassed_bombsite]['bscore'] += (self.BOMBSITE_COEFFICIENT[unreachable_size] * self.unreachable_bscore_coefficient) if self.my_side == 'Police': bombsite_positions = sorted(self.bombsites, key = lambda x: self.bombsites[x]['initial_distance']) self.clusters, self.cluster_centers = kmeans(bombsite_positions, len(my_agents)) self.cluster_index = [0] * len(my_agents) print(self.clusters,self.cluster_centers) # prevent passing by exploding bombs for bomb in self.world.bombs: if bomb.explosion_remaining_time == 1: for neighbor in bomb.position.get_neighbours(self.world): self.world.board[neighbor.y][neighbor.x] = ECell.Wall if self.my_side == 'Terrorist': # update bombsites if bomb(s) is defused if self.last_scores['Police'] != self.world.scores['Police']: bomb_count = len(self.world.bombs) for last_bomb in self.last_bombs: for index,bomb in enumerate(self.world.bombs): if bomb.position == last_bomb.position: break elif index == bomb_count - 1: bombsite_position = self._position_to_tuple(last_bomb.position) if bombsite_position in self.bombsites: self.bombsites[bombsite_position]['status'] = -1 self.bombsites[bombsite_position]['failed'] += 2 self.last_bombs = self.world.bombs # choose nearest agent for each bombsite if bombsites number is smaller than agents number not_planted_bombsites = 0 for bombsite in self.bombsites: if self.bombsites[bombsite]['status'] != 2: not_planted_bombsites += 1 if not_planted_bombsites < len(alive_agents): for agent_id,agent in enumerate(my_agents): if agent.planting_remaining_time == -1: self.target_bombsites[agent_id] = None for bombsite in self.bombsites: if self.bombsites[bombsite]['status'] != 2: min_distance = 1000 for agent in alive_agents: if not self.target_bombsites[agent.id]: distance, _ = self._a_star(agent.position,bombsite) if distance < min_distance: best_agent = agent.id min_distance = distance self.bombsites[bombsite]['task'] = 1 self.target_bombsites[best_agent] = bombsite print('targets:',self.target_bombsites) else:# police # update bombsites status according to sounds and visions for bombsite in self.bombsites: if self.bombsites[bombsite]['status'] < 0: self.bombsites[bombsite]['status'] += 1 in_vision_bombs = [] for bomb in self.world.bombs: bombsite = self._position_to_tuple(bomb.position) self.bombsites[bombsite]['brt'] = bomb.explosion_remaining_time in_vision_bombs.append(bombsite) for agent in alive_agents: if agent.defusion_remaining_time == -1: for bombsite in self.bombsites: if self.bombsites[bombsite]['status'] >= 0: if self._heuristic(bombsite,agent.position) <= self.world.constants.police_vision_distance: if not bombsite in in_vision_bombs: if self._heuristic(bombsite,agent.position) == 1: self.bombsites[bombsite]['status'] = -1 * self.world.constants.bomb_planting_time - 1 else: self.bombsites[bombsite]['status'] = -2 self.bombsites[bombsite]['task'] = 0 else: self.bombsites[bombsite]['status'] = 2 sound_counts = {ESoundIntensity.Weak:0,ESoundIntensity.Normal:0,ESoundIntensity.Strong:0} in_range_sites = {ESoundIntensity.Weak:[],ESoundIntensity.Normal:[],ESoundIntensity.Strong:[]} for sound in agent.bomb_sounds: sound_counts[sound] += 1 for bombsite in self.bombsites: if self._heuristic(bombsite,agent.position) <= self.world.constants.sound_ranges[ESoundIntensity.Weak]: distance, _ = self._a_star(agent.position, bombsite, not_valid_ecells=[ECell.Wall],agent_block=False) if distance: minimum_distance = self.world.constants.police_vision_distance for sound_kind in self.sound_kinds: if distance <= self.world.constants.sound_ranges[sound_kind] and distance > minimum_distance: if sound_counts[sound_kind]: status = self.bombsites[bombsite]['status'] in_range_sites[sound_kind].append((bombsite,status,distance)) else: self.bombsites[bombsite]['status'] = -2 if self.target_bombsites[agent.id] == bombsite: self.checked_bombsites[agent.id].append(bombsite) break minimum_distance = self.world.constants.sound_ranges[sound_kind] for sound_kind in self.sound_kinds: if sound_counts[sound_kind] > 0: possibles,sures = [], [] for index,(bombsite,status,distance) in enumerate(in_range_sites[sound_kind]): if status >= 2: sures.append(bombsite) elif status >= 0: possibles.append(bombsite) if len(sures) == sound_counts[sound_kind]: for bombsite in possibles: self.bombsites[bombsite]['status'] = -2 else: status = int((len(sures) + len(possibles)) <= sound_counts[sound_kind]) + 1 for bombsite in possibles: self.bombsites[bombsite]['status'] = status # print(agent.id,'at',agent.position,bombsite,status,in_range_sites) for bombsite in self.bombsites: if self.bombsites[bombsite]['ert'] > -1: self.bombsites[bombsite]['ert'] -= 1 elif self.bombsites[bombsite]['status'] == 2: self.bombsites[bombsite]['ert'] = self.world.constants.bomb_explosion_time self.last_scores = self.world.scores # print(self.bombsites) for agent in alive_agents: if self.my_side == 'Police': bombsite_direction = self._find_bombsite_direction(agent) doing_bomb_operation = (agent.defusion_remaining_time != - 1) if doing_bomb_operation: # defusing bombsite_position = self._sum_pos_tuples(self.DIR_TO_POS[bombsite_direction],(agent.position.y,agent.position.x)) self._agent_print(agent.id, 'Continuing bomb operation') self.bombsites[bombsite_position]['status'] = 2 if agent.defusion_remaining_time == 1: self.bombsites[bombsite_position]['status'] = -1 * self.world.constants.bomb_planting_time - 1 self.bombsites[bombsite_position]['task'] = 0 continue if bombsite_direction: try: multiple = len(bombsite_direction) except: multiple = False if multiple: bombsite_direction = bombsite_direction[0] bombsite_position = self._sum_pos_tuples(self.DIR_TO_POS[bombsite_direction],(agent.position.y,agent.position.x)) if self.target_bombsites[agent.id] == bombsite_position or multiple: for bomb in self.world.bombs: if self._position_to_tuple(bomb.position) == bombsite_position: if bomb.explosion_remaining_time < self.world.constants.bomb_defusion_time: has_time = False else: has_time = True break if has_time: self._agent_print(agent.id, 'Starting bomb operation') self.defuse(agent.id, bombsite_direction) self.bombsites[bombsite_position]['task'] = 2 continue else: # self.scape_bombsite(agent) self._agent_print(agent.id, 'direction: Ignoring bomb due to lack of time :(') self.bombsites[bombsite_position]['status'] = 3 self.bombsites[bombsite_position]['task'] = 1 self.bombsites[bombsite_position]['agent'] = -1 if self.world.bombs and not bombsite_direction: # bomb in vision: found = False for bomb in self.world.bombs: bombsite_position = self._position_to_tuple(bomb.position) if self.bombsites[bombsite_position]['task'] < 2 and self.bombsites[bombsite_position]['status'] < 3 and self.target_bombsites[agent.id] == bombsite_position and self._heuristic(agent.position,bombsite_position) <= self.world.constants.police_vision_distance: distance, path = self._a_star(agent.position, bomb.position) time_needed = distance + self.world.constants.bomb_defusion_time if time_needed < bomb.explosion_remaining_time: found = True self.bombsites[bombsite_position]['task'] = 1 self.bombsites[bombsite_position]['agent'] = agent.id self.path_move(agent,path) self._agent_print(agent.id, 'Going to defuse.') break # print('time status:',time_needed,bomb.explosion_remaining_time) else: self._agent_print(agent.id, 'Ignoring bomb due to lack of time :(') self.bombsites[bombsite_position]['task'] = 1 self.bombsites[bombsite_position]['agent'] = -1 self.bombsites[bombsite_position]['status'] = 3 if found: continue # patrol: cluster = self.clusters[agent.id] if cluster: best_bombsite, (best_distance, best_path) = self.best_bombsite_patrol(agent) if best_path: if len(best_path) > 1: self.path_move(agent, best_path) else: # len(bombsites) < len(agents) pass else: # terrorist if self.last_position[agent.id] == agent.position: self.gir_count[agent.id] += 1 else: self.gir_count[agent.id] = 0 self.last_position[agent.id] = agent.position bombsite_direction = self._find_bombsite_direction(agent) doing_bomb_operation = agent.planting_remaining_time != -1 threatened = False if ESoundIntensity.Strong in agent.footstep_sounds: self.heard_sound_count[agent.id] += 1 else: self.heard_sound_count[agent.id] = 0 if doing_bomb_operation: try: multiple = len(bombsite_direction) except: multiple = False if multiple: bombsite_direction = bombsite_direction[0] bombsite_position = self.target_bombsites[agent.id] if self.heard_sound_count[agent.id] >= (self.world.constants.terrorist_vision_distance - self.world.constants.police_vision_distance): threatened = True # self.heard_sound_count[agent.id] = 0 if not threatened: self.gir_count[agent.id] = 0 if agent.planting_remaining_time <= 1: self._agent_print(agent.id, 'Finishing bomb operation') self.bombsites[bombsite_position]['task'] = 0 self.bombsites[bombsite_position]['status'] = 2 self.target_bombsites[agent.id] = None else: self._agent_print(agent.id, 'Continuing bomb operation') self.bombsites[bombsite_position]['task'] = 2 else: self._agent_print(agent.id, 'I swear I heard police footsteps, time to look around or maybe scape') if len(self._empty_directions(agent.position)) == 1: self.scape_bombsite(agent) else: self.move(agent.id, agent.position.direction_to(Position(bombsite_position[1],bombsite_position[0]))) self.bombsites[bombsite_position]['task'] = 1 continue if bombsite_direction: bombsite_position = self._sum_pos_tuples(self.DIR_TO_POS[bombsite_direction],(agent.position.y,agent.position.x)) threatening_polices = [] for police in self.world.polices: distance = self._heuristic(police.position,agent.position) if distance <= self.world.constants.terrorist_vision_distance and police.status == EAgentStatus.Alive: threatening_polices.append(police) if threatening_polices: self.scape_polices(agent,threatening_polices) threatened = True self.bombsites[bombsite_position]['failed'] += 1 self._agent_print(agent.id, "I see police(s). I can always plant, Now I must Scape.") continue if not threatened and self.bombsites[bombsite]['task'] != 2: if bombsite_position == self.target_bombsites[agent.id] and self.bombsites[bombsite_position]['failed'] <= 5: self._agent_print(agent.id, "Starting bomb operation, I don't see any polices.") self.plant(agent.id, bombsite_direction) self.bombsites[bombsite_position]['task'] = 2 continue # go to best bombsite if self.gir_count[agent.id] >= 4: self._agent_print(agent.id, "Doing random move because GIR KARDAM !!!") self.move(agent.id, random.choice(self._empty_directions(agent.position))) continue best_bombsite, best_distance, best_path = self.best_bombsite_plant(agent) if len(best_path) > 1: # there IS a possible bombsite self.bombsites[best_bombsite]['task'] = 1 self.target_bombsites[agent.id] = best_bombsite self.last_distance[agent.id] = best_distance self._agent_print(agent.id, 'Going to bombsite.') self.path_move(agent,best_path) else: # no bombsites left to plant threatening_polices = [] for police in self.world.polices: if self._heuristic(agent.position,police.position) <= self.world.constants.police_vision_distance + 1: threatening_polices.append(police) if threatening_polices: self.scape_polices(agent,threatening_polices) self._agent_print(agent.id, 'Nothing to do, Scaping police(s).') continue else: bombsite_position = self._find_bombsite_direction(agent,possible_only=False) if bombsite_position: self.scape_bombsite(agent) self._agent_print(agent.id, 'Nothing to do, Getting a safe distance with the last planted bomb.') continue else: self._agent_print(agent.id, 'Nothing to do, waiting ZzZzZ...') # if self.my_side == 'Police': # for agent_1 in patrol_moves: # for agent_2 in patrol_moves: # if agent_1 != agent_2 and self._position_to_tuple(agent_1.position) == patrol_moves[agent_2] and self._position_to_tuple(agent_2.position) == patrol_moves[agent_1]: # self.cluster_index[agent_1.id],self.cluster_index[agent_2.id] = self.cluster_index[agent_2.id],self.cluster_index[agent_1.id] # bombsite_position_1 = self.bombsite_positions[self.cluster_index[agent_1.id]] # bombsite_position_2 = self.bombsite_positions[self.cluster_index[agent_2.id]] # _, path_1 = self._a_star(agent_1.position, bombsite_position_1) # _, path_2 = self._a_star(agent_2.position, bombsite_position_1) # patrol_moves[agent_1] = path_1[1] # patrol_moves[agent_2] = path_2[1] # for agent in patrol_moves: # if patrol_moves[agent]: # self.position_move(agent,patrol_moves[agent]) # else: # print(self.heard_sound_count) if self.my_side == 'Police': print(self.target_bombsites) # print(self.bombsites) # for bombsite in self.bombsites: # print(bombsite,'status:',self.bombsites[bombsite]['status'],'task:',self.bombsites[bombsite]['task'],end=',') # print() end = time.time() print('time:',end - start)
def _position_from_tuple(t): return Position(x=t[0], y=t[1])
def position_move(self,agent,position): # try: direction = agent.position.direction_to(Position(x=position[1],y=position[0])) self.move(agent.id, direction) agent.position = Position(x=position[1],y=position[0])
def _dist_between(self, goal,agent_positions=[],police_positions=[], bombsite_block = True): dist_between = 1 min_distance = 1000 for police_position in police_positions: distance = self._heuristic(goal,police_position) if distance < min_distance: min_distance = distance if min_distance <= self.world.constants.police_vision_distance + 1: dist_between += abs(min_distance - (self.world.constants.police_vision_distance + 2)) * 1000 elif min_distance == self.world.constants.police_vision_distance + 2 and len(self._empty_directions(Position(y=goal[0],x=goal[1]))) == 1: dist_between += 2000 if not bombsite_block: if self.world.board[goal[0]][goal[1]] != ECell.Wall and self.world.board[goal[0]][goal[1]] != ECell.Empty: dist_between += 100 return dist_between
def _a_star(self, start_position, goal_position, valid_ecells=[ECell.Empty],not_valid_ecells=None,agent_block=True,bombsite_block=True): start = self._position_to_tuple(start_position) goal = self._position_to_tuple(goal_position) blocked_by_agent = False if not not_valid_ecells: check = self._check_valid ecells = valid_ecells else: check = self._check_not_valid ecells = not_valid_ecells if not bombsite_block: ecells = [ECell.Empty] for ecell in self.BOMBSITES_ECELL: ecells.append(ecell) police_positions = [] agent_positions = [] if agent_block: if self.my_side == 'Police': agents = self.world.polices else: agents = self.world.terrorists for police in self.world.polices: if police.status == EAgentStatus.Alive: police_positions.append(police.position) for agent in agents: if agent.status == EAgentStatus.Alive and self._position_to_tuple(agent.position) != start: agent_positions.append(agent.position) closed_set = {} # key: position, value: f_score open_set = {start: self._heuristic(start, goal)} came_from = {} g_score = {start: 0} min_blocking_distance = 100000 while open_set: current = min(open_set, key=open_set.get) if current == goal: return self._reconstruct_path(came_from, current, bombsite_block=bombsite_block) del open_set[current] closed_set[current] = True for neighbor_position in Position(x=current[1],y=current[0]).get_neighbours(self.world): neighbor = (neighbor_position.y,neighbor_position.x) if neighbor in closed_set: continue if not check(self.world.board[neighbor[0]][neighbor[1]],ecells) and neighbor != goal: continue if agent_block: if neighbor_position in agent_positions: if self._heuristic(goal,neighbor_position) < min_blocking_distance: best_blocking_neighbor = neighbor best_blocking_current = current min_blocking_distance = self._heuristic(goal,neighbor_position) + self._dist_between(neighbor,agent_positions,police_positions) blocked_by_agent = True continue tentative_g_score = g_score[current] + self._dist_between(neighbor,agent_positions,police_positions, bombsite_block=bombsite_block) if tentative_g_score > 1000: continue if neighbor in open_set and tentative_g_score >= g_score[neighbor]: continue came_from[neighbor] = current g_score[neighbor] = tentative_g_score open_set[neighbor] = g_score[neighbor] + self._heuristic(neighbor, goal) if blocked_by_agent: came_from[best_blocking_neighbor] = best_blocking_current return self._reconstruct_path(came_from,best_blocking_neighbor) if bombsite_block: return None, [] else: return None, [], []
def first_terrorist_strategy(self, agent: Terrorist): # If there's a police near, change direction and run! police_positions, police_pos, police = [], None, None for polices in self.world.polices: if AI._distance( polices.position, agent.position ) <= self.world.constants.terrorist_vision_distance: police_positions.append(polices.position) police = polices # Escaping from two or more polices: if len(police_positions) > 1: escape_directions = self._escape_direction(agent, police_positions[0])[1] for police_pos in police_positions[1:]: escape_directions = list( set(escape_directions) & set(self._escape_direction(agent, police_pos)[1])) selected_direction, directions = None, self._empty_directions( agent) for direction in escape_directions: if direction in directions: selected_direction = direction break if selected_direction: if agent.id in self.terrorist_bomb_site: del self.terrorist_bomb_site[agent.id] if agent.id in self.path: del self.path[agent.id] self.waiting_counter[agent.id] = 1 self.move(agent.id, selected_direction) self.print("Escaping from two or more polices to: ", end='') self.print(selected_direction) return True elif len(police_positions) == 1: police_pos = police_positions[0] # A police found around, let's make sure that he/she is defusing a bomb or not: for bomb in self.world.bombs: if bomb.defuser_id == police.id: # Police is defusing a bomb, let's escape from a better way! self.bomb_defuser_pos = (police.position.y, police.position.x) black_pos = self._calculate_black_pos(agent) # Although we are not escaping from a police, we should watch out for defuser police position! black_pos.append(self.bomb_defuser_pos) g = Graph(self.world, (agent.position.y, agent.position.x), black_pos) dest = self._terrorist_destination( agent, (police_pos.y, police_pos.x)) path = g.bfs(dest) if police.defusion_remaining_time and police.defusion_remaining_time < len( path): aim_point = path[police.defusion_remaining_time - 1] if self._distance( police.position, Position(aim_point[1], aim_point[0]) ) > self.world.constants.police_vision_distance: # Escapeeeeeeee. police_pos = None self.terrorist_bomb_site[agent.id] = dest self.path[agent.id] = path break ''' police_pos = None for police in self.world.polices: if AI._distance(police.position, agent.position) <= self.world.constants.terrorist_vision_distance: police_pos = police.position ''' if police_pos: selected_direction = self._escape_direction(agent, police_pos)[0] if selected_direction: if agent.id in self.terrorist_bomb_site: del self.terrorist_bomb_site[agent.id] if agent.id in self.path: del self.path[agent.id] self.waiting_counter[agent.id] = 1 self.move(agent.id, selected_direction) else: # Let's try our chance and speculate where police wants to go after this cycle, then escape! stay = False for bomb in self.world.bombs: if self._distance( bomb.position, agent.position ) <= self.world.constants.terrorist_vision_distance: stay = True break if not stay: g = Graph(self.world, (police_pos.y, police_pos.x)) police_path = g.bfs((agent.position.y, agent.position.x)) self.print("Police speculated path while escaping:") self.print(police_path) if police_path: selected_direction = self._escape_direction( agent, Position(police_path[0][1], police_path[0][0]))[0] if agent.id in self.terrorist_bomb_site: del self.terrorist_bomb_site[agent.id] if agent.id in self.path: del self.path[agent.id] self.waiting_counter[agent.id] = 1 self.move(agent.id, selected_direction) return True return False
def path_move(self,agent,path): direction = agent.position.direction_to(Position(x=path[1][1],y=path[1][0])) self.move(agent.id, direction) agent.position = Position(x=path[1][1],y=path[1][0])