from collections import defaultdict import random import robots iter_board = robots.utils.iter_board DIRECTIONS = robots.game.DIRECTIONS def shuffled(items): items = list(items) random.shuffle(items) return items def get_enemy_robots(me, players): robots = {} for name, info in players.items(): if name != me: for x, y in info['robots']: robots[x, y] = name return robots def paths_to_enemies(enemies, board, iterations=None): width = len(board[0]) height = len(board) if iterations is None: iterations = 10 iterations = width * height distances = [] for y in range(height): distances.append([]) for x in range(width): if (x, y) in enemies: value = (0, None, (x, y)) else: value = (float('inf'), None, None) distances[-1].append(value) DIRECTION_ITEMS = shuffled(DIRECTIONS.items()) for i in range(iterations): for y in range(height): for x in range(width): for move, (dx, dy) in DIRECTION_ITEMS: nx = (x + dx) % width ny = (y + dy) % height if board[ny][nx] == '*': continue current_dist = distances[y][x][0] this_dist, _, dest = distances[ny][nx] this_dist += 1 if this_dist < current_dist: distances[y][x] = (this_dist, move, dest) return distances def attacker(whoami, players, board): width = len(board[0]) height = len(board) my_robots = players[whoami]['robots'] enemies = get_enemy_robots(whoami, players) paths = paths_to_enemies(enemies, board) allocations = defaultdict(list) for x, y in my_robots: dist, dir, dest = paths[y][x] allocations[dest].append((dist, dir, (x, y))) searchers = int(len(my_robots) * 0.7) assignments = {} for options in allocations.values(): for dist, dir, robot in sorted(options)[:searchers]: assignments[robot] = dir results = [] for x, y in my_robots: choice = assignments.get((x, y)) if board[y][x] != whoami and (not choice or random.random() < 0.5): choice = 'P' elif choice: pass else: moves = [] for dir, (dx, dy) in DIRECTIONS.items(): nx = (x + dx) % width ny = (y + dy) % height if board[ny][nx] != '*': moves.append(dir) choice = random.choice(moves or '-') results.append(choice) return ''.join(results) def never_paint(whoami, players, board): my_robots = players[whoami]['robots'] return ''.join( random.choice('ULD--') for _ in range(len(my_robots)) ) def bot(whoami, players, board): my_robots = players[whoami]['robots'] return ''.join( random.choice('ULDRP-') for _ in range(len(my_robots)) ) if __name__ == '__main__': # random.seed(42) map_ = robots.border_map(30, 10, 0) for y in range(8): map_[y][10] = '*' for y in range(11, 2, -1): map_[y][20] = '*' map_[5][5] = '1' map_[5][15] = '2' map_[5][25] = '3' game = robots.Game(map_) # game.add_bot(attacker, 'Alice') # game.add_bot(attacker, 'Adam') game.add_bot(attacker, 'Barry') game.add_bot(attacker, 'Bob') game.add_bot(never_paint, 'Baldrick') viewer = robots.CursesViewer(game) viewer.run()