Example #1
0
def h_walldist(state, fline, walls, grid):
    """
    The new version of h_walldist no longer calls edist_grid, but instead takes
    the grid as a fourth argument. It retrieves the current position's grid value,
    and adds an estimate of how long it will take to stop. 
    """

    ((x,y),(u,v)) = state
    hval = float(grid[x][y])   
    # if this state is going to lead us to crashing, then no.
    ebest = op.opponent1((x,y),(u,v),fline,walls)
    if rt.crash(((x,y),(x+u+ebest[0],y+v+ebest[1])),walls):
        hval = infinity    
   
    # add a small penalty to favor short stopping distances
    au = abs(u); av = abs(v); 
    sdu = au*(au-1)/2.0
    sdv = av*(av-1)/2.0
    sd = max(sdu,sdv)
    penalty = sd/10.0

    # compute location after fastest stop, and add a penalty if it goes through a wall
    if u < 0: sdu = -sdu
    if v < 0: sdv = -sdv
    sx = x + sdu
    sy = y + sdv
    if rt.crash([(x,y),(sx,sy)],walls):
        hval = infinity
    #hval = max(hval+penalty,sd)


    return hval
def next_states(state, f_line, walls):
    """Return a list of states we can go to from state"""
    states = []
    (loc, (vx, vy)) = state
    for dx in [0, -1, 1, -2, 2]:
        for dy in [0, -1, 1, -2, 2]:
            (wx, wy) = (vx + dx, vy + dy)
            newloc = (loc[0] + wx, loc[1] + wy)
            err = opponent1(loc, (wx, wy), f_line, walls)
            errloc = (newloc[0] + err[0], newloc[1] + err[1])
            if (not rt.crash((loc, errloc), walls) and not rt.crash(
                (loc, newloc), walls)
                    and not ((wx, wy) != 0 and (errloc == loc))):
                states.append((errloc, (wx, wy)))
    return states
Example #3
0
def edist_grid2(fline, walls):
    global grid
    xmax = max([max(x, x1) for ((x, y), (x1, y1)) in walls])
    ymax = max([max(y, y1) for ((x, y), (x1, y1)) in walls])
    grid = [[edistw_to_finish((x, y), fline, walls) for y in range(ymax + 1)]
            for x in range(xmax + 1)]
    flag = True
    print('computing edist grid', end=' ')
    sys.stdout.flush()
    while flag:
        print('.', end='')
        sys.stdout.flush()
        flag = False
        for x in range(xmax + 1):
            for y in range(ymax + 1):
                for y1 in range(max(0, y - 1), min(ymax + 1, y + 2)):
                    for x1 in range(max(0, x - 1), min(xmax + 1, x + 2)):
                        if grid[x1][y1] != infinity and not rt.crash(
                            ((x, y), (x1, y1)), walls):
                            if x == x1 or y == y1:
                                d = grid[x1][y1] + 1
                            else:
                                # In principle, it seems like a taxicab metric should be just as
                                # good, but Euclidean seems to work a little better in my tests.
                                d = grid[x1][y1] + 1.4142135623730951
                            if d < grid[x][y]:
                                grid[x][y] = d
                                flag = True
    print(' done')
    return grid
Example #4
0
def h_walldist(state, fline, walls, grid):
    """
    The new version of h_walldist no longer calls edist_grid, but instead takes
    the grid as a fourth argument. It retrieves the current position's grid value,
    and adds an estimate of how long it will take to stop. 
    """
    ((x, y), (u, v)) = state
    hval = float(grid[x][y])

    # add a small penalty to favor short stopping distances
    au = abs(u)
    av = abs(v)
    sdu = au * (au - 1) / 2.0
    sdv = av * (av - 1) / 2.0
    sd = max(sdu, sdv)
    penalty = sd / 10.0

    # compute location after fastest stop, and add a penalty if it goes through a wall
    if u < 0: sdu = -sdu
    if v < 0: sdv = -sdv
    sx = x + sdu
    sy = y + sdv
    if rt.crash([(x, y), (sx, sy)], walls):
        penalty += math.sqrt(au**2 + av**2)
    hval = max(hval + penalty, sd)
    return hval
Example #5
0
def my_states(state, walls, fline):
    """
    Returns a set of possible states that we can move to starting at the
    given state.

    We trim states that will crash, states that will lead to certain death,
    and states that have locations we have been to before.
    """

    data2_file = open('data2.txt', 'r')
    history = json.load(data2_file)
    data2_file.close()

    ((x, y), (u, v)) = state
    states = set()
    for delta_x in [-2, -1, 0, 1, 2]:
        for delta_y in [-2, -1, 0, 1, 2]:
            move = ((x, y), (x + delta_x, y + delta_y))
            new_state = ((x + delta_x, y + delta_y), (delta_x, delta_y))
            if not rt.crash(move, walls) and str(new_state[0]) not in history:
                if hit_or_near_goal(state, fline):
                    # If that state is a goal we MUST be able to go to it (if we don't crash trying to do so).
                    states.add(new_state)
                elif not moving_to_this_state_straight_up_kill_you(
                        new_state, walls):
                    # But, if it is NOT a goal then we can only go to it if we don't crash along the way and if moving to it won't kill us.
                    states.add(new_state)

    return states
Example #6
0
def edistw_to_finish(point, fline, walls):
    """
    straight-line distance from (x,y) to the finish line ((x1,y1),(x2,y2)).
    Return infinity if there's no way to do it without intersecting a wall
    """
    #   if min(x1,x2) <= x <= max(x1,x2) and  min(y1,y2) <= y <= max(y1,y2):
    #       return 0
    (x, y) = point
    ((x1, y1), (x2, y2)) = fline
    # make a list of distances to each reachable point in fline
    if x1 == x2:  # fline is vertical, so iterate over y
        ds = [math.sqrt((x1-x)**2 + (y3-y)**2) \
            for y3 in range(min(y1,y2),max(y1,y2)+1) \
            if not rt.crash(((x,y),(x1,y3)), walls)]
    else:  # fline is horizontal, so iterate over x
        ds = [math.sqrt((x3-x)**2 + (y1-y)**2) \
            for x3 in range(min(x1,x2),max(x1,x2)+1) \
            if not rt.crash(((x,y),(x3,y1)), walls)]
    ds.append(infinity)  # for the case where ds is empty
    return min(ds)
Example #7
0
def moving_to_this_state_straight_up_kill_you(state, walls):
    """
    Returns true if moving to this state is certain death. False otherwise.
    """

    wall_hit = False
    for child in control_error_states(state):
        loc = state[0]
        new_loc = child[0]
        if rt.crash((loc, new_loc), walls):
            wall_hit = True
    return wall_hit
def edistw_to_finish(point, fline, walls):
    """
        The function from h_walldist:
        straight-line distance from (x,y) to the finish line ((x1,y1),(x2,y2)).
        Return infinity if there's no way to do it without intersecting a wall
        :param a: point, fline, walls
        :return: straight-line distance from point to finish line (considering walls)
        """

    (x, y) = point
    ((x1, y1), (x2, y2)) = fline
    # make a list of distances to each reachable point in fline
    if x1 == x2:  # fline is vertical, so iterate over y
        ds = [math.sqrt((x1 - x) ** 2 + (y3 - y) ** 2) \
              for y3 in range(min(y1, y2), max(y1, y2) + 1) \
              if not racetrack.crash(((x, y), (x1, y3)), walls)]
    else:  # fline is horizontal, so iterate over x
        ds = [math.sqrt((x3 - x) ** 2 + (y1 - y) ** 2) \
              for x3 in range(min(x1, x2), max(x1, x2) + 1) \
              if not racetrack.crash(((x, y), (x3, y1)), walls)]
    ds.append(infinity)  # for the case where ds is empty
    return min(ds)
Example #9
0
def edist_grid(fline, walls):
    """
    This functions creates a grid to cache values in the graph. Walls and 
    unreachable nodes are stored as infinity. The function uses a BFS
    to traverse the grid and find distance values to each node from the
    finish line.
    """
    global grid
    xmax = max([max(x, x1) for ((x, y), (x1, y1)) in walls])
    ymax = max([max(y, y1) for ((x, y), (x1, y1)) in walls])
    visited = []
    # initialize grid
    grid = [[infinity for y in range(ymax + 1)] for x in range(xmax + 1)]
    # get all reachable points from finish and mark as visited
    for x in range(xmax + 1):
        for y in range(ymax + 1):
            grid[x][y] = edistw_to_finish((x, y), fline, walls)
            if grid[x][y] != infinity:
                visited.append((x, y))
    queue = visited[:]
    inifinity_states = []
    while queue:
        (x, y) = queue.pop(0)
        # for each neighbor of the first node in queue
        infinity_flag = False
        for y1 in range(max(0, y - 1), min(ymax + 1, y + 2)):
            for x1 in range(max(0, x - 1), min(xmax + 1, x + 2)):
                # if a neighbor is not a wall and not visited
                # add it to queue and mark as visited
                # then update grid with new value for (x, y)
                if not rt.crash(((x, y), (x1, y1)), walls):
                    if (x1, y1) not in visited:
                        queue.append((x1, y1))
                        visited.append((x1, y1))
                    if x == x1 or y == y1:
                        d = grid[x1][y1] + 1
                    else:
                        # In principle, it seems like a taxicab metric should be just as
                        # good, but Euclidean seems to work a little better in my tests.
                        d = grid[x1][y1] + 1.4142135623730951
                    if d < grid[x][y]:
                        grid[x][y] = d
                else:
                    infinity_flag = True
        if infinity_flag:
            inifinity_states.append((x, y))

    # set all wall neighbors to infinity
    for (x, y) in inifinity_states:
        grid[x][y] = infinity
    return grid
def oppcrashcheck(prev, state, walls, n2finish):
    """
    oppcrashcheck will take into account of the error and check if with the error the path from
    previous state to current state crashes.

    :param: prev, state, walls, n2finish: near fline points
    :return: if path from prev to current state crashes.
    """
    (x1, y1) = prev
    (x2, y2) = state
    # check if it's near fline and its velocity if (0, 0)
    if state in n2finish and prev == state:
        return False
    for i in range(x2 - 1, x2 + 2):
        for j in range(y2 - 1, y2 + 2):
            # check if it crashes
            if racetrack.crash([(x1, y1), (i, j)], walls):
                return True
    return False
Example #11
0
def h_proj1(state, fline, walls, grid):
    """
    The first time this function is called, for each gridpoint that's not inside a wall
    it will cache a rough estimate of the length of the shortest path to the finish line.
    The computation is done by a breadth-first search going backwards from the finish 
    line, one gridpoint at a time.
    
    On all subsequent calls, this function will retrieve the cached value and add an
    estimate of how long it will take to stop. 
    """
    ((x, y), (u, v)) = state

    # if a crash can be caused, return infinity
    #(dbest, ebest) = opponent1((x,y),(u,v), fline, walls)
    #if (dbest == 0):
    #    return infinity

    # if there are no walls between state and finish, use h_esdist
    if edistw_to_finish(
        (x, y), fline, walls) != infinity and grid[x][y] != infinity:
        return h_esdist(state, fline, walls)
    hval = float(grid[x][y])

    # add a small penalty to favor short stopping distances
    au = abs(u)
    av = abs(v)
    sdu = au * (au - 1) / 2.0
    sdv = av * (av - 1) / 2.0
    sd = max(sdu, sdv)
    penalty = sd / 10.0

    # compute location after fastest stop, and add a penalty if it goes through a wall
    if u < 0: sdu = -sdu
    if v < 0: sdv = -sdv
    sx = x + sdu
    sy = y + sdv
    if rt.crash([(x, y), (sx, sy)], walls):
        penalty += math.sqrt(au**2 + av**2)
    hval = max(hval + penalty, sd)
    return hval
Example #12
0
def main(state,finish,walls):
    """
    main function is to calculate for the best velocity of this current state. We put our solution in choices.txt.
    First, I added the current state to visited state list (using data2.txt)
    Second, I checked for the current state
    if it's the goal and velocity (u,v) is in range of (0,0) then the best velocity is (0,0) and we win.
    If not, we're going to look for the best velocity by searching for the best next state and velocity.
    Third, we might found some velocity that make us progress in a loop, we will avoid that checking if the next state is visited.
    Lastly, we return our best velocity choice.
    """
    ((x,y), (u,v)) = state

    
    # Retrieve the grid data that the "initialize" function stored in data.txt
    data_file = open('data.txt', 'r')
    grid = json.load(data_file)
    data_file.close()
    
    
    choices_file = open('choices.txt', 'w')
    
    # Add visited state to the file data2.txt
    if (u,v) == (0,0) and edist_to_line((x,y),finish) > 1:
        data_file = open('data2.txt', 'w')
        visited = []
        visited.append((x,y))
        json.dump(visited,data_file)
        data_file.close()
    else:
        data_file = open('data2.txt', 'r')
        visited = json.load(data_file)
        data_file.close()
        data_file = open('data2.txt', 'w')
        visited.append((x,y))
        json.dump(visited,data_file)
        data_file.close()
        
    # Take the new version of h_walldist, which needs the grid as a 4th argument, and
    # translate it into the three-argument function needed by rt.main
    h = lambda state,fline,walls: h_walldist(state,fline,walls,grid)    

    # We checked if this current state can be the end
    if edist_to_line((x,y),finish) <= 1 and abs(u) <= 2 and abs(v) <= 2:
        velocity = (0,0)
        print('  proj2_example: finishing, new velocity =', velocity)
        
    # We search for the best velocity
    else:
        path = rt.main(state,finish,walls,'gbf', h, verbose=0, draw=0)
        #print('  proj2_example: path =', path)
        for i in range(len(path)):
            #print('  proj2_example: path[',i,'] =', path[i])
            if path[i] == state:
                print('  proj2_example: found state', state)
                velocity = path[i+1][1]
                
                # the case to handle if the velocity will lead us to crashing
                ebest = op.opponent1((x,y),(velocity[0],velocity[1]),finish,walls)
                if rt.crash(((x,y),(x+velocity[0]+ebest[0],y+velocity[1]+ebest[1])),walls):
                    velocity = (velocity[0]-ebest[0],velocity[1]-ebest[1])
                
                data_file = open('data2.txt', 'r')
                visited = json.load(data_file)
                data_file.close()
                
                # the case to handle if the velocity will lead us to visited states
                if visited is not None:
                    ebest = op.opponent1((x,y),(velocity[0],velocity[1]),finish,walls)
                    if [x+velocity[0]+ebest[0],y+velocity[1]+ebest[1]] in visited:
                        velocity = (velocity[0]-ebest[0],velocity[1]-ebest[1])
                        ebest = op.opponent1((x,y),(velocity[0],velocity[1]),finish,walls)

                print('  proj2_example: new velocity', velocity)
                break
            
    # need to flush because Python uses buffered output
    print(velocity,file=choices_file,flush=True)
def h_opp(state, fline, walls):
    """
    The first time this function is called, it will use optimized breath first search to find the cost for all the
    points on the grid.
    On all subsequent calls, this function will retrieve the cached value and add an
    estimate of how long it will take to stop.
    :param a: state, fline, walls
    :return: estimate cost of the step
    """
    global g_fline, g_walls

    if fline != g_fline or walls != g_walls or grid == []:
        bfs(fline, walls)
    ((x, y), (u, v)) = state
    if x > xm or x < 0 or y > ym or y < 0: return infinity  # add on
    ((h1, w1), (h2, w2)) = fline
    li = listfl(fline)
    hval = float(grid[x][y])

    au = abs(u)
    av = abs(v)
    sdu = au * (au - 1) / 2.0
    sdv = av * (av - 1) / 2.0
    sd = max(sdu, sdv)

    if u < 0: sdu = -sdu
    if v < 0: sdv = -sdv
    sx = x + sdu
    sy = y + sdv

    # check if it has already found a solution path
    # if yes, stop exploring other nodes
    if li.count((x, y)) > 0 and u == 0 and v == 0:
        return negainfinity

    # add a small penalty to favor short stopping distances
    penalty = sd

    # compute location after stop, and add a penalty if it goes through a wall
    if racetrack.crash([(x, y), (sx, sy)], walls):
        penalty += 1.1 * math.sqrt(au ** 2 + av ** 2)
    else:
        penalty -= sd / 10.0

    # compute the slowest stopping distance
    if au % 2 == 0:
        ssu = (au - 2) * au / 4
    else:
        ssu = (au - 1) * au / 4
    if av % 2 == 0:
        ssv = (av - 2) * av / 4
    else:
        ssv = (av - 1) * av / 4
    if u < 0: ssu = -ssu
    if v < 0: ssv = -ssv
    ssx = x + int(ssu)
    ssy = y + int(ssv)

    if not racetrack.crash([(x, y), (ssx, ssy)], walls):
        # check if the slowest stop point land on the fline
        # if yes, significantly reduce the return cost
        if (ssx, ssy) in li:
            penalty -= sd / 4.0
        # check if the slowest stopping x or y point is on the fline and reduce the return cost
        elif li.count((h1, ssy)) > 0 or li.count((h2, ssy)) > 0 or li.count((ssx, w1)) > 0 or li.count((ssx, w2)) > 0:
            penalty -= sd / 10.0

    hval += penalty

    return hval
def bfs(fline, walls):
    """
        Use a breath-first-search from the fline to compute costs for points on the grid
        (combine edistw_to_finish and edist_grid into one time traversal of the nodes;
        significantly reduce the runtime)
        :param: fline, walls
        :return: return the grid
        """
    global grid, g_fline, g_walls, xmax, ymax
    xmax = max([max(x, x0) for ((x, y), (x0, y0)) in walls])
    ymax = max([max(y, y0) for ((x, y), (x0, y0)) in walls])
    grid = [[infinity for i in range(ymax + 1)] for j in range(xmax + 1)]
    ((x1, y1), (x2, y2)) = fline
    frontier = deque([])
    visited = []

    # set the points on fline as 0 in the grid
    # and put all neighbors of the fline in the frontier
    if x1 == x2:
        for y3 in range(min(y1, y2), max(y1, y2) + 1):
            grid[x1][y3] = 0
            visited.append((x1, y3))

        for y3 in range(min(y1, y2), max(y1, y2) + 1):
            for n in range(max(0, y3 - 1), min(ymax + 1, y3 + 2)):
                for m in range(max(0, x1 - 1), min(xmax + 1, x1 + 2)):
                    if frontier.count((m, n)) == 0 and grid[m][n] == infinity:
                        frontier.append((m, n))
    else:
        for x3 in range(min(x1, x2), max(x1, x2) + 1):
            grid[x3][y1] = 0
            visited.append((x3, y1))

        for x3 in range(min(x1, x2), max(x1, x2) + 1):
            for n in range(max(0, y1 - 1), min(ymax + 1, y1 + 2)):
                for m in range(max(0, x3 - 1), min(xmax + 1, x3 + 2)):
                    if frontier.count((m, n)) == 0 and grid[m][n] == infinity:
                        frontier.append((m, n))

    # use breath-first-search to compute the costs in the grid
    while frontier:
        (v1, v2) = frontier.popleft()
        visited.append((v1, v2))
        grid[v1][v2] = edistw_to_finish((v1, v2), fline, walls)

        # check if edistw_to_finish is able to compute the cost
        # if not, compute the cost using its non-infinity neighbors
        if grid[v1][v2] == infinity:

            for g in range(max(0, v1 - 1), min(xmax + 1, v1 + 2)):
                for h in range(max(0, v2 - 1), min(ymax + 1, v2 + 2)):
                    if grid[g][h] != infinity and not racetrack.crash(((v1, v2), (g, h)), walls):
                        if g == v1 or h == v2:
                            d = grid[g][h] + 1
                        else:

                            d = grid[g][h] + 1.4142135623730951
                        if d < grid[v1][v2]:
                            grid[v1][v2] = d

        if grid[v1][v2] != infinity:
            for i in range(max(0, v1 - 1), min(xmax + 1, v1 + 2)):
                for j in range(max(0, v2 - 1), min(ymax + 1, v2 + 2)):
                    if frontier.count((i, j)) == 0 and visited.count((i, j)) == 0:  ##and grid[i][j] == infinity:
                        frontier.append((i, j))

    g_fline = fline
    g_walls = walls
    return grid