def calculate_distance_field(game: Game, source: Pt, target: Pt):
    # Calculate and return a distance field from the target, over visited cells only
    sentinel = object()
    front = deque([source, sentinel])
    distfield = {source: 0}
    generation = 1
    found = False
    while front:
        p = front.popleft()
        if p == sentinel:
            if found:
                break
            assert front
            generation += 1
            front.append(sentinel)
            continue

        for d in Action.DIRS.keys():
            p2 = p + d
            if (p2 not in distfield and game.in_bounds(p2)
                    and game.is_passable(p2)):
                distfield[p2] = generation
                front.append(p2)
                if p2 == target:
                    found = True
    return distfield
def calculate_spanning_tree(game: Game, pos: Pt):
    front = deque([pos])
    visited = {pos: Treenode(pos, None)}
    found = None

    while front:
        p = front.popleft()
        pnode = visited[p]
        for d in Action.DIRS.keys():
            p2 = p + d
            if (p2 not in visited and game.in_bounds(p2)
                    and game.is_passable(p2)):
                visited[p2] = Treenode(p2, pnode)
                pnode.children.append(visited[p2])
                front.append(p2)

    visited[pos].fill_stats(game)
    return visited
示例#3
0
def solve(game: Game,
          params: dict) -> Tuple[Optional[int], List[List[Action]], dict]:
    cnt = 0

    params['booster_count'] = sum(1 for b in game.boosters if b.code == 'B')
    map_center = Pt(game.grid.width // 2, game.grid.height // 2)
    teleport_list = []

    while not game.finished():
        cnt += 1
        if cnt % 1000 == 0:
            logging.info(f'{game.remaining_unwrapped} unwrapped')

        bot = game.bots[0]
        extensions = {
            b.pos
            for b in game.boosters if b.code in params['boostlist']
        }
        prev = {bot.pos: None}
        frontier = [bot.pos]

        # searching target
        depth = 0
        while frontier:
            best_rank = 0
            dst = None
            for p in frontier:
                rank = 0
                if p in extensions:
                    rank += 5
                for m in bot.manipulator:
                    q = p + m
                    if (game.in_bounds(q) and game.grid[q] == '.'
                            and not game.is_wrapped(q)
                            and visible(game.grid, q, p)):
                        rank += 1
                if rank > best_rank:
                    best_rank = rank
                    dst = p
            if dst is not None:
                break

            new_frontier = []
            if depth == 0 and 'R' in params['boostlist']:
                new_frontier = teleport_list[:]
                for p in new_frontier:
                    prev[p] = bot.pos

            for p in frontier:
                for d in Action.DIRS.keys():
                    p2 = p + d
                    if (p2 not in prev and game.in_bounds(p2) and
                        (game.grid[p2] == '.' or bot.drill_timer - depth > 0)):

                        prev[p2] = p
                        new_frontier.append(p2)
            frontier = new_frontier
            depth += 1

        assert dst is not None
        assert dst != bot.pos

        # teleport
        if 'R' in params['boostlist'] and game.inventory['R'] > 0:
            if map_center.manhattan_dist(
                    bot.pos) < map_center.manhattan_dist(dst):
                game.apply_action(Action.reset())
                logger.info('reset teleport')
                teleport_list.append(bot.pos)

        # gathering path
        path = []
        p = dst
        while p != bot.pos:
            d = p - prev[p]
            if d not in Action.DIRS.keys():
                assert 'R' in params['boostlist'] and p in teleport_list
                path.append(Action.teleport(p.x, p.y))
                logger.info('teleport away')
            else:
                path.append(Action.DIRS[d])
            p = prev[p]
            assert p is not None
        path.reverse()

        assert depth == len(path), (depth, len(path))

        for a in path:
            game.apply_action(a)
        if params['best score'] is not None and game.turn >= params[
                'best score']:
            return None, [], {}

        # boosters
        if game.inventory['B'] > 0:
            logger.info('attach extension')
            params['attach func'](game, params, 0)

        if 'L' in params['boostlist'] and game.inventory['L'] > 0:
            logger.info('use drill')
            game.apply_action(Action.drill())

    score = game.finished()
    logger.info(game.inventory)

    extra = dict(final_manipulators=len(game.bots[0].manipulator))

    return score, game.get_actions(), extra
示例#4
0
def solve(task: Task,
          turns: str,
          bestscore=None) -> Tuple[Optional[int], List[List[Action]], dict]:
    task = GridTask(task)

    game = Game(task)

    cnt = 0

    for t in turns:
        game.apply_action(Action.simple(t))

    while not game.finished():
        cnt += 1
        if cnt % 1000 == 0:
            logging.info(f'{game.remaining_unwrapped} unwrapped')
        extensions = {b.pos for b in game.boosters if b.code == 'B'}
        prev = {game.bots[0].pos: None}
        frontier = [game.bots[0].pos]
        while frontier:
            best_rank = 0
            dst = None
            for p in frontier:
                rank = 0
                if p in extensions:
                    rank += 5
                rank += len(
                    manipulators_will_wrap(game.grid, game._wrapped, p,
                                           game.bots[0].manipulator))
                if rank > best_rank:
                    best_rank = rank
                    dst = p
            if dst is not None:
                break

            new_frontier = []
            for p in frontier:
                for d in Action.DIRS.keys():
                    p2 = p + d
                    if (p2 not in prev and game.in_bounds(p2)
                            and game.grid[p2] == '.'):

                        prev[p2] = p
                        new_frontier.append(p2)
            frontier = new_frontier

        assert dst is not None
        assert dst != game.bots[0].pos

        path = []
        p = dst
        while p != game.bots[0].pos:
            d = p - prev[p]
            path.append(Action.DIRS[d])
            p = prev[p]
            assert p is not None
        path.reverse()
        for a in path:
            game.apply_action(a)
        if bestscore is not None and game.turn >= bestscore:
            return None, [], {}

        if game.inventory['B'] > 0:
            logger.info('attach extension')
            attach_to = Pt(1, len(game.bots[0].manipulator) - 2)
            for t in turns:
                attach_to = turn_pt(attach_to, t)
            game.apply_action(Action.attach(attach_to.x, attach_to.y))

    score = game.finished()
    logger.info(game.inventory)

    extra = dict(final_manipulators=len(game.bots[0].manipulator))

    return score, game.get_actions(), extra
示例#5
0
    def draw(self, game: Game, extra_status=''):
        stdscr, pad = self.stdscr, self.pad

        def char(p, char, fgcolor):
            offset = Pt(1, 1)
            if game.in_bounds(p) and game.is_wrapped(p):
                bg_color = curses.COLOR_BLUE
            else:
                bg_color = curses.COLOR_BLACK
            p = p + offset
            pad.addstr(self.height - p.y + 1, p.x * 2, char + ' ',
                       colormapping[fgcolor, bg_color])

        bot = game.bots[(self.current - 1) % len(game.bots)]
        area = max(
            bot.pos.manhattan_dist(bot.pos + m) for m in bot.manipulator)

        for y in range(bot.pos.y - area, bot.pos.y + area + 1):
            for x in range(bot.pos.x - area, bot.pos.x + area + 1):
                p = Pt(x, y)
                if not game.in_bounds(p):
                    continue
                char(p, game.grid[p], FgColors.Dungeon)

        for b in game.boosters:
            char(b.pos, b.code, FgColors.Booster)

        for t in game.teleport_spots:
            char(t, '+', FgColors.Spot)

        for c in game.clone_spawn:
            char(c, 'X', FgColors.Spot)

        for b in game.bots:
            for m in bot.manipulator:
                w = b.pos + m
                if game.in_bounds(w) and geom.visible(game.grid, b.pos, w):
                    char(m, '*', FgColors.Manipulator)

        for b in game.bots:
            char(b.pos, '@', FgColors.InactivePlayer)

        char(game.bots[self.current].pos, '@', FgColors.Player)

        offset = self.screen_offset(game.size(), bot.pos)
        pad.refresh(offset.y, offset.x, 0, 0, curses.LINES - 2,
                    curses.COLS - 1)

        if self.last_error:
            status_line = self.last_error.ljust(curses.COLS)[:curses.COLS - 1]
            self.last_error = ''
            stdscr.addstr(
                curses.LINES - 1, 0, status_line,
                colormapping[curses.COLOR_YELLOW | BRIGHT, curses.COLOR_RED])
        else:
            status_line = f'turn={game.turn} ' + \
                          f'pos=({bot.pos.x}, {bot.pos.y}) ' + \
                          f'unwrapped={game.remaining_unwrapped} '
            status_line += ' '.join(f'{b}={game.inventory[b]}'
                                    for b in Booster.PICKABLE)

            if game.bots[self.current].wheels_timer:
                status_line += f' WHEELS({game.bots[self.current].wheels_timer})'

            if game.bots[self.current].drill_timer:
                status_line += f' DRILL({game.bots[self.current].drill_timer})'

            if extra_status:
                status_line += ' '
                status_line += extra_status
            # LMAO: "It looks like simply writing the last character of a window is impossible with curses, for historical reasons."
            status_line = status_line.ljust(curses.COLS)[:curses.COLS - 1]
            stdscr.addstr(
                curses.LINES - 1, 0, status_line,
                colormapping[curses.COLOR_YELLOW | BRIGHT, curses.COLOR_BLUE])

        stdscr.refresh()
示例#6
0
def solve(task: Task) -> Tuple[int, List[List[Action]], dict]:
    task = GridTask(task)

    game = Game(task)

    cnt = 0
    while not game.finished():
        cnt += 1
        if cnt % 1000 == 0:
            logging.info(f'{game.remaining_unwrapped} unwrapped')
        prev = {game.bots[0].pos: None}
        frontier = [game.bots[0].pos]
        while frontier:
            best_rank = 0
            dst = None
            for p in frontier:
                rank = len(
                    manipulators_will_wrap(game.grid, game._wrapped, p,
                                           game.bots[0].manipulator))
                if rank > best_rank:
                    best_rank = rank
                    dst = p
            if dst is not None:
                break

            new_frontier = []
            for p in frontier:
                for d in Action.DIRS.keys():
                    p2 = p + d
                    if (p2 not in prev and game.in_bounds(p2)
                            and game.grid[p2] == '.'):

                        prev[p2] = p
                        new_frontier.append(p2)
            frontier = new_frontier

        assert dst is not None
        assert dst != game.bots[0].pos

        path = []
        p = dst
        while p != game.bots[0].pos:
            d = p - prev[p]
            path.append(Action.DIRS[d])
            p = prev[p]
            assert p is not None
        path.reverse()
        for a in path:
            game.apply_action(a)

        if game.inventory['B'] > 0:
            logger.info('attach extension')
            game.apply_action(
                Action.attach(1,
                              len(game.bots[0].manipulator) - 2))

    score = game.finished()
    logger.info(game.inventory)

    extra = dict(final_manipulators=len(game.bots[0].manipulator))

    return score, game.get_actions(), extra