def followRightWall(unit, map):
    
    if unit.id not in currentDirections:
        currentDirections[unit.id] = goToWall(unit, map)
    
    (x, y) = apply_direction(unit.x, unit.y, currentDirections[unit.id].value)
    
    if((x<0 or y<0 or x>=len(map[0]) or y >= len(map))
        and (currentDirections[unit.id].value % 2)==0):
        currentDirections[unit.id] = Direction((currentDirections[unit.id].value - 2) % 8)
    
    i = 2
    (x, y) = apply_direction(unit.x, unit.y, (currentDirections[unit.id].value + i) % 8)
    direction = Direction((currentDirections[unit.id].value + i) % 8)
    # starts at direction right to current direction
    # and checks if it as a valid location to move to
    # then sequentially points counter-clockwise until a valid direction is found
    while(x<0 or y<0 or x>=len(map[0]) or y >= len(map) or 
        map[y][x]!=0):
        i -= 1
        direction = Direction((currentDirections[unit.id].value + i) % 8)
        (x, y) = apply_direction(unit.x, unit.y, direction.value)
    # update current facing direction and return direction to move
    currentDirections[unit.id] = direction
    return direction
def isAtWall(unit, map):
    (x, y) = apply_direction(unit.x, unit.y, Direction.NORTH.value)
    if(x<0 or y<0 or x>=len(map[0]) or y >= len(map)):
        return True
    (x, y) = apply_direction(unit.x, unit.y, Direction.EAST.value)
    if(x<0 or y<0 or x>=len(map[0]) or y >= len(map)):
        return True
    (x, y) = apply_direction(unit.x, unit.y, Direction.SOUTH.value)
    if(x<0 or y<0 or x>=len(map[0]) or y >= len(map)):
        return True
    (x, y) = apply_direction(unit.x, unit.y, Direction.WEST.value)
    if(x<0 or y<0 or x>=len(map[0]) or y >= len(map)):
        return True
    return False
def chooseRandom(unit, map):
    direction = Direction.STILL
    (x, y) = (unit.x, unit.y)
    # keep choosing a random direction until the direction is legal
    # also prevents unit from standing still
    while(direction==Direction.STILL or 
        x<0 or y<0 or x>=len(map[0]) or y >= len(map) or
        map[y][x]!=0):
        direction = random.choice(list(Direction))
        (x, y) = apply_direction(unit.x, unit.y, direction.value)
    return direction
def isSufficientlySurrounded(unit, map):
    surroundingObstacles = 0
    for direction in Direction:
        if(direction==Direction.STILL):
            continue
        (x, y) = apply_direction(unit.x, unit.y, direction.value)
        if(x<0 or y<0 or x>=len(map[0]) or y >= len(map) or map[y][x]==1):
            surroundingObstacles += 1
    if(surroundingObstacles >= 6):
        return True
    else:
        return False
def goToWall(unit, map):
    # gets closest point to the closest wall
    (targetx, targety) = getClosestWall(unit, map)
    # a Dictionary to keep track of possible directions to move
    possibleDirections = {}
    for direction in Direction:
        (x, y) = apply_direction(unit.x, unit.y, direction.value)
        #discount illegal directions
        if(direction==Direction.STILL or 
            x<0 or y<0 or x>=len(map[0]) or y >= len(map) or
            map[y][x]!=0):
            pass
        # map distances to each direction
        else:
            possibleDirections[direction] = getDistance(x, y, targetx, targety)
    # return direction that is shortest
    return min(possibleDirections, key=possibleDirections.get)
def chooseAntDirection(unit, map):
    if unit.id not in currentDirections:
        currentDirections[unit.id] = Direction.STILL
                
    (x, y) = apply_direction(unit.x, unit.y, currentDirections[unit.id].value)
    # if unit hits a wall or has no assigned direction            
    if(currentDirections[unit.id]==Direction.STILL or
        x<0 or y<0 or x>=len(map[0]) or y >= len(map) or
        map[y][x]!=0):
        # assign a random direction for it            
        currentDirections[unit.id] = chooseRandom(unit, map)
        direction = currentDirections[unit.id]
    # otherwise, continue in its current direction                
    else:
        direction = currentDirections[unit.id]

    return direction
def antiGreedy(current, enemy, map):
    bestDirection = None
    farthestDistance = 0
    # for each possible direction, figure out its distance to the target
    for direction in Direction:
        (x, y) = apply_direction(current.x, current.y, direction.value)
        # if direction is still or not legal, continue with the loop
        if(direction==Direction.STILL or 
            x<0 or y<0 or x>=len(map[0]) or y >= len(map) or
            map[y][x]!=0):
            continue
        # figure out the farthest distance
        distance = getDistance(x, y, enemy.x, enemy.y)
        if (distance > farthestDistance):
            bestDirection = direction
            farthestDistance = distance
    # return the best direction
    return bestDirection
def greedy(current, target, map):
    bestDirection = None
    closestDistance = math.inf
    # for each possible direction, figure out its distance to the target
    for direction in Direction:
        (x, y) = apply_direction(current.x, current.y, direction.value)
        # if direction is still or not legal, continue with the loop
        if(direction==Direction.STILL or 
            x<0 or y<0 or x>=len(map[0]) or y >= len(map) or
            map[y][x]!=0):
            continue
        # figure out the shortest distance
        distance = getDistance(x, y, target.x, target.y)
        if (distance < closestDistance):
            bestDirection = direction
            closestDistance = distance
    # return the best direction
    return bestDirection
Ejemplo n.º 9
0
def handle(agent: Agent, commands: list):
    for _, unit in enumerate(agent.units):
        game_map = agent.map  # the map
        # unit.id is id of the unit
        # unit.x unit.y are its coordinates, unit.distance is distance away from nearest opponent
        # game_map is the 2D map of what you can see.
        # game_map[i][j] returns whats on that tile, 0 = empty, 1 = wall,
        # anything else is then the id of a unit which can be yours or the opponents

        # get direction from a human controller
        myDirection = getdirectionvalue(unit, agent)

        # apply direction to current unit's position to check if that new position is on the game map
        (x, y) = apply_direction(unit.x, unit.y, myDirection)
        if (x < 0 or y < 0 or x >= len(game_map[0]) or y >= len(game_map)):
            # we do nothing if the new position is not in the map
            # TODO notify human and request to display 'Hit the wall' on the server
            pass
        else:
            commands.append(unit.move(myDirection))
                    if not reachedWall[unit.id]:
                        direction = goToWall(unit, game_map)
                        currentDirections[unit.id] = direction

                    else:
                        direction = followRightWall(unit, game_map)

            # if hiders seen, apply basic greedy alorithm to move closer to it
            else:
                reachedWall[unit.id] = False
                closestEnemy = opposingUnits[0]
                direction = greedy(unit, closestEnemy, game_map)
                currentDirections[unit.id] = direction
            
            # apply direction to current unit's position to check if that new position is on the game map
            (x, y) = apply_direction(unit.x, unit.y, direction.value)
            if (x < 0 or y < 0 or x >= len(game_map[0]) or y >= len(game_map)):
                # we do nothing if the new position is not in the map
                pass
            else:
                commands.append(unit.move(direction.value))

            index += 1
        
    else:
        index = 0       # index is depracated
        for _, unit in enumerate(units):
            # to keep track of units that need to get to the wall initally
            if unit.id not in reachedWall:
                reachedWall[unit.id] = False
            if (not reachedWall[unit.id]) and isAtWall(unit, game_map):
Ejemplo n.º 11
0
    if (agent.team == Team.SEEKER):
        # AI Code for seeker goes here

        for _, unit in enumerate(units):
            # unit.id is id of the unit
            # unit.x unit.y are its coordinates, unit.distance is distance away from nearest opponent
            # game_map is the 2D map of what you can see.
            # game_map[i][j] returns whats on that tile, 0 = empty, 1 = wall,
            # anything else is then the id of a unit which can be yours or the opponents

            # choose a random direction to move in
            randomDirection = random.choice(list(Direction)).value

            # apply direction to current unit's position to check if that new position is on the game map
            (x, y) = apply_direction(unit.x, unit.y, randomDirection)
            if (x < 0 or y < 0 or x >= len(game_map[0]) or y >= len(game_map)):
                # we do nothing if the new position is not in the map
                pass
            else:
                commands.append(unit.move(randomDirection))

    else:
        # AI Code for hider goes here
        # hider code, which does nothing, sits tight and hopes it doesn't get
        # found by seekers
        pass

    # submit commands to the engine
    print(','.join(commands))
Ejemplo n.º 12
0
def main(logs):
    global seed

    def log(msg, unitid=None, level='INFO'):
        if level == 'DEBUG' and not verbose:
            return
        for flog in logs:
            identity = agent.team.name if unitid == None else '{} {}'.format(
                agent.team.name, unitid)
            flog.write('{} [{}] <{}>: {}\n'.format(time.asctime(), level,
                                                   identity, msg))
            flog.flush()

    def vlog(*args, **kwargs):
        # if verbose:
        log(*args, **kwargs, level='DEBUG')

    if seed == None:
        seed = random.getrandbits(32)
    random.seed(seed)
    log('Competition started with team seed: {}'.format(seed))
    agent.init_log(log, len(logs) > 0)
    agent.post_log_init()

    while True:
        vlog('Round #{}/200 begins'.format(agent.round_num))
        commands = []
        units = agent.units  # list of units you own
        opposingUnits = agent.opposingUnits  # list of units on other team that you can see
        # game_map = agent.map # the map
        round_num = agent.round_num  # the round number

        vlog('Visible opponent ids: {}'.format(
            list(map(lambda unit: unit.id, opposingUnits))))
        agent.opponents_update()
        if need_human:
            human.handle(agent, commands)
        else:
            if agent.team == Team.SEEKER:
                # AI Code for seeker goes here
                # for _, unit in enumerate(units):
                for unit in units:

                    def ulog(*args, **kwargs):
                        log(*args, **kwargs, unitid=unit.id)

                    def uvlog(*args, **kwargs):
                        vlog(*args, **kwargs, unitid=unit.id)

                    # unit.id is id of the unit
                    # unit.x unit.y are its coordinates, unit.distance is distance away from nearest opponent
                    # game_map is the 2D map of what you can see.
                    # game_map[i][j] returns whats on that tile, 0 = empty, 1 = wall,
                    # anything else is then the id of a unit which can be yours or the opponents

                    uvlog('Location: {}. R^2 distance to closest opponent {}.'.
                          format((unit.x, unit.y), unit.distance))

                    # # choose a random direction to move in
                    # myDirection = random.choice(list(Direction)).value

                    # # apply direction to current unit's position to check if that new position is on the game map
                    # (x, y) = apply_direction(unit.x, unit.y, myDirection)
                    # if (x < 0 or y < 0 or x >= len(game_map[0]) or y >= len(game_map)):
                    #     # we do nothing if the new position is not in the map
                    #     pass
                    # else:
                    #     commands.append(unit.move(myDirection))
                    closest_dist = math.inf
                    lowest_uncertainty = math.inf
                    best_moves = []  # Do nothing and stay still
                    # primary_target = False # target has primary location, usually in sight
                    # dead_hider_ids = []
                    for op in mod_op.opponents.values():
                        # lastloc = op.get_primary_loc()
                        lastloc = op.lastseen
                        if lastloc != None:
                            goto = lastloc
                        else:
                            # goto = random.choice() # FIXME for seed reasons
                            goto = op.possible_list[0]
                            # ulog('FIXME: no primary locations!', level='WARN')
                            # pass # FIXME use more advanced pathing (Ex. sweep search) in this case
                        uncertainty = op.location_count
                        opx, opy = goto
                        try:
                            nxdir, dist = agent.pathing(
                                unit.x, unit.y, opx, opy)
                            uvlog('Distance to opponent {}: {}'.format(
                                op.id, dist))
                            assert len(nxdir) > 0
                            if dist <= 1:
                                ulog(
                                    "Hider {} should be dead and shouldn't be on the stage!"
                                    .format(op.id),
                                    level='WARN')
                                # dead_hider_ids.append(op.id)
                            else:
                                if (uncertainty, dist) < (lowest_uncertainty,
                                                          closest_dist):
                                    closest_dist = dist
                                    lowest_uncertainty = uncertainty
                                    if op.primary_loc != None:
                                        uvlog(
                                            'Greedily selecting next move from {} by distance'
                                            .format(list(map(Direction,
                                                             nxdir))))
                                        bestmv = None
                                        r2distbest = math.inf
                                        for candidate in nxdir:
                                            cdist = vision.distance_squared(
                                                *apply_direction(
                                                    unit.x, unit.y, candidate),
                                                opx, opy)
                                            if cdist < r2distbest:
                                                r2distbest = cdist
                                                bestmv = candidate
                                        best_moves = [bestmv]
                                    else:
                                        best_moves = nxdir
                        except NoPath:
                            ulog('No path to hider ID {}'.format(op.id))
                    # for dead_hider_id in dead_hider_ids:
                    #     del opponents[dead_hider_id]
                    if len(best_moves) == 0:
                        if opponents:
                            ulog('No best next move!', level='WARN')
                    else:
                        uvlog('Possible next moves: {}'.format(
                            list(map(Direction, best_moves))))
                        my_move = random.choice(best_moves)
                        uvlog('Actually moving toward: {}'.format(
                            Direction(my_move)))
                        commands.append(unit.move(my_move))

                if not opponents:
                    log('No opponents left')
            else:
                # AI Code for hider goes here
                # hider code, which does nothing, sits tight and hopes it doesn't get
                # found by seekers
                if debug:
                    agent.debug_distance_map(agent.seeker_map)
                for unit in units:

                    def ulog(*args, **kwargs):
                        log(*args, **kwargs, unitid=unit.id)

                    def uvlog(*args, **kwargs):
                        vlog(*args, **kwargs, unitid=unit.id)

                    myinfo = unit.get_info()
                    hider_state = myinfo.hider_state
                    if hider_state == HiderState.FRESH:
                        loop_candidates = set()
                        viable_target_cells = []
                        my_distance_map = agent.generate_distance_map([
                            (unit.x, unit.y)
                        ])
                        for y in range(agent.ydim):
                            for x in range(agent.xdim):
                                if my_distance_map[y][
                                        x] != math.inf and my_distance_map[y][
                                            x] + 2 <= agent.seeker_map[y][x]:
                                    for loop in agent.loop_index[y][x]:
                                        viable_target_cells.append((x, y))
                                        loop_candidates.add(loop)
                        ulog('Viable loops: {}'.format(
                            list(
                                map(
                                    lambda loop: ((loop.x0, loop.y0),
                                                  (loop.x1, loop.y1)),
                                    loop_candidates))))
                        if len(loop_candidates) == 0:
                            ulog('Unable to find a viable loop!', level='WARN')
                        else:
                            for other in units:
                                otherinfo = other.get_info()
                                if len(loop_candidates) > 1:
                                    if other is not unit and otherinfo.hider_loop != None and otherinfo.hider_loop in loop_candidates:
                                        loop_candidates.remove(
                                            otherinfo.hider_loop)
                                else:
                                    break
                            hider_loop: Loop = random.choice(
                                list(loop_candidates))
                            myinfo.hider_loop = hider_loop
                            ulog('Chosen loop: {} to {}'.format(
                                (hider_loop.x0, hider_loop.y0),
                                (hider_loop.x1, hider_loop.y1)))
                            # for px, py in hider_loop.cell_set:
                            for px, py in viable_target_cells:
                                for other in units:
                                    if other.get_info().hiding_target == (px,
                                                                          py):
                                        break
                                else:
                                    myinfo.hiding_target = (px, py)
                                    break
                            assert myinfo.hiding_target != None
                            ulog('Chosen hiding target {}'.format(
                                myinfo.hiding_target))
                            if myinfo.hiding_target == None:
                                hidex, hidey = viable_target_cells[0]
                                ulog(
                                    'Have to share hiding target with another unit all @ {}!'
                                    .format((hidex, hidey)),
                                    level='ERROR')
                                myinfo.hiding_target = (hidex, hidey)
                            ulog('Chosen hiding target: {}'.format(
                                myinfo.hiding_target))
                            hider_state = HiderState.HIDING
                    elif hider_state == HiderState.HIDING:
                        nxdir, dist = agent.pathing(unit.x, unit.y,
                                                    myinfo.hiding_target[0],
                                                    myinfo.hiding_target[1])
                        if dist == 0:
                            hider_state = HiderState.CIRCLING
                            ulog('Entered circling state')
                        else:
                            chosendir = random.choice(nxdir)
                            uvlog('Moving with direction {} toward {} to hide'.
                                  format(Direction(chosendir),
                                         myinfo.hiding_target))
                            commands.append(unit.move(chosendir))
                    if hider_state == HiderState.CIRCLING:
                        uvlog('Circling: seeker distance here: {}'.format(
                            agent.seeker_map[unit.y][unit.x]))
                        maxdist = agent.seeker_map[unit.y][
                            unit.x]  # Not moving take precedence
                        mdmove = 8
                        # Greedily choose the lowest distance
                        for dirnum, (dx,
                                     dy) in enumerate(kit.direction_deltas):
                            nx = unit.x + dx
                            ny = unit.y + dy
                            if agent.walkable(nx, ny) and (
                                    nx, ny) in myinfo.hider_loop.cell_set:
                                newdist = agent.seeker_map[ny][nx]
                                if newdist >= maxdist:
                                    mdmove = dirnum
                                    maxdist = newdist
                        uvlog(
                            'Moving toward {} for greatest seeker distance {}'.
                            format(Direction(mdmove), maxdist))
                        commands.append(unit.move(mdmove))
                    unit.get_info().hider_state = hider_state

        # vlog('Submitting commands...')
        # submit commands to the engine
        print(','.join(commands))

        # vlog('Sending end turn command...')
        # now we end our turn
        agent.end_turn()

        vlog('Round ended. Waiting for updates from engine...')
        # wait for update from match engine
        agent.update()
        vlog('Updated bot based on response from engine.')