def solve(self, task: str) -> SolverResult: task = Task.parse(task) task = GridTask(task) game = Game(task) if not game.clone_spawn: return SolverResult(data=Pass(), expected_score=None, extra=dict(reason='no clone spawns')) if not game.inventory['C'] and not game.map_contains_booster('C'): return SolverResult(data=Pass(), expected_score=None, extra=dict(reason='no clone boosters')) cnt = 0 while not game.finished(): cnt += 1 if cnt % 200 == 0: logging.info( f'{len(game.bots)} bots; {game.remaining_unwrapped} unwrapped' ) used_bots = [False for bot in game.bots] actions = [None for bot in game.bots] orig_bots = game.bots[:] if game.clone_spawn and game.inventory['C']: logging.info('need spawn') df = DistanceField(game.grid) df.build(game.clone_spawn) dist = df.dist best_rank = 1e10 best_bot = None best_action = None for bot_index, bot in enumerate(orig_bots): if dist[bot.pos] == 0: continue for d, a in Action.DIRS.items(): p = bot.pos + d if not game.grid.in_bounds(p): continue rank = dist[p] if rank < best_rank: best_rank = rank best_bot = bot_index best_action = a #assert best_bot is not None #game.apply_action(best_action, best_bot) if best_bot is not None: actions[best_bot] = best_action used_bots[best_bot] = True boosters = [b.pos for b in game.boosters if b.code == 'C'] if not game.finished() and game.clone_spawn and not game.inventory[ 'C'] and boosters and not all(used_bots): df = DistanceField(game.grid) df.build(boosters) dist = df.dist best_rank = 1e10 best_bot = None best_action = None for bot_index, bot in enumerate(orig_bots): if used_bots[bot_index]: continue for d, a in Action.DIRS.items(): p = bot.pos + d if not game.grid.in_bounds(p): continue rank = dist[p] if rank < best_rank: best_rank = rank best_bot = bot_index best_action = a assert best_bot is not None actions[best_bot] = best_action used_bots[best_bot] = True if game.finished(): break df = DistanceField(game.grid) starts = list_unwrapped(game._wrapped) df.build(starts) dist = df.dist for bot_index, bot in enumerate(orig_bots): if game.finished(): break if used_bots[bot_index]: game.apply_action(actions[bot_index], bot_index) continue if game.inventory['C'] and bot.pos in game.clone_spawn: game.apply_action(Action.clone(), bot_index) logging.info('clone!!!') continue if game.inventory['B'] > 0: logger.info('attach extension') game.apply_action( Action.attach(1, len(game.bots[0].manipulator) - 2)) continue best_rank = 1e10 best_action = None for d, a in Action.DIRS.items(): p = bot.pos + d if not game.grid.in_bounds(p): continue rank = dist[p] for j, bot2 in enumerate(orig_bots): if j < bot_index: d = bot.pos.manhattan_dist(bot2.pos) rank += 10 * max(0, 30 - d) if rank < best_rank: best_rank = rank best_action = a assert best_action is not None game.apply_action(best_action, bot_index) expected_score = score = game.finished() extra = dict(final_bots=len(game.bots)) return SolverResult(data=compose_actions(game.get_actions()), expected_score=expected_score, extra=extra)