Esempio n. 1
0
    def construct_path(self, start, end):

        # Rooms the path can go through
        allowedRooms = list(self.waypointRooms[start] | self.waypointRooms[end])

        # Queue of paths so far
        frontierPaths = Queue.PriorityQueue()
        frontierPaths.put([0, [start], 0])

        # Dict of points reached so far (to keep contains() at O(1))
        visited = dict()
        visited[start] = True

        while not frontierPaths.empty():

            currentNode = frontierPaths.get()
            currentPath = currentNode[1]  # A list of waypoints

            # Check if we've reached the goal - if so, terminate pathfinding
            currentWaypoint = currentPath[-1]
            if currentWaypoint == end:

                # Concatenate all the steps between the waypoints together
                currentSteps = []
                for i in range(0, len(currentPath) - 1):

                    a = currentPath[i+1]
                    b = currentPath[i]

                    fullPath = self.allPaths[a][b]
                    currentSteps.extend(fullPath)

                return (currentSteps, currentPath)

            # Expand it
            for nextWaypoint in self.availableConnections[currentWaypoint]:

                # Don't include already-visited points
                if nextWaypoint in visited:
                    continue

                # Don't include waypoints in non-allowed rooms
                inAllowedRooms = False
                for r in self.waypointRooms[nextWaypoint]:
                    if r in allowedRooms:
                        inAllowedRooms = True
                        break
                if not inAllowedRooms:
                    continue

                # Mark next waypoint as visited
                visited[nextWaypoint] = True

                # Add path to frontier
                nextPath = self.allPaths[nextWaypoint][currentWaypoint]
                travelled = currentNode[2] + len(nextPath) * self.mapConstants["path_step_size"]
                dist = vecLen(end, nextWaypoint)
                frontierPaths.put([travelled + dist, currentPath + [nextWaypoint], travelled])

        # No paths found
        print '\033[91mERROR: no path found between ' + str(start) + ' --> ' + str(end) + '\033[0m'
        return ([], [])
Esempio n. 2
0
    def turn(self, turn=None):
        while self.running and self.update_state(json.loads(turn)):

            # Get paths
            for p in self.people:
                p.path = []
                if p.pos != p.targetPos:
                    (p.path, p.waypoints) = self.construct_path(p.pos, p.targetPos)
                    p.pathLength = len(p.path)

            # Smooth moving
            framesLeft = float(self.constants["FRAMES_PER_TURN"])
            movementFinalized = False
            while framesLeft >= 0 or not movementFinalized:
                movementFinalized = self.movementIsComplete()

                self.draw()
                self.update()
                self.GameClock.tick(self.MAX_FPS)

                framesLeft -= 1.0

                for p in self.people:

                    # --- Calculate path length ---
                    # Initial float
                    iterSteps = float(p.pathLength) / float(self.constants["FRAMES_PER_TURN"])

                    # Smooth float part out over frames
                    iterSteps = math.ceil(framesLeft * iterSteps) - math.floor((framesLeft - 1) * iterSteps)

                    # Keep people moving at a minimum pace
                    iterSteps = min(iterSteps, self.constants["MIN_STEPS_PER_FRAME"])
                    # ------ End path length ------

                    if p.path and len(p.path) > iterSteps:

                        for i in range(0, int(iterSteps)):
                            p.pos = p.path[0]
                            p.path.pop(0)

                        # Adjust rotation
                        rotationLookahead = self.constants["ROTATION_LOOKAHEAD"]
                        if len(p.path) > rotationLookahead:
                            p.set_rotation(angleBetween(p.pos, p.path[rotationLookahead]) - 90)
                        else:
                            p.set_rotation(angleBetween(p.pos, p.targetPos) - 90)

                    else:
                        p.pos = p.targetPos
                        p.path = []

                        # Check for direction marker, otherwise just keep current rotation
                        for d in self.rooms[p.room].dirmarkers:
                            if vecLen(d, p.pos) < self.constants["DIR_MARKER_RADIUS"]:
                                p.set_rotation(angleBetween(p.pos, d) - 90)
                                break

                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        self.running = False
                        movementFinalized = True
            if self.running:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        self.running = False
            if not self.game_done:
                break
Esempio n. 3
0
def _findShortestValidPath(start, end, roomColor, pixels, imgSize, stepSize=1):

    # Ace settings
    playerSize = 4  # Should be 12, use 4 for testing
    playerStep = 4

    # seen
    seen = dict()
    seen[(start[0], start[1])] = ((-1, -1), 0, False)

    # Queues
    nodeQueue = Queue.PriorityQueue()
    nodeQueue.put((0.0, 0.0, start[0], start[1]))

    width = imgSize[0]
    height = imgSize[1]

    # Do BFS
    pathFound = False
    node = None
    while not nodeQueue.empty():

        node = nodeQueue.get()
        coord = node[2:]
        seenval = seen[coord]
        seen[coord] = (seenval[0], seenval[1], True)

        x = coord[0]
        y = coord[1]

        # Base case 1: too close to a wall
        pathIsValid = True
        for i in range(x - playerSize, x + playerSize + 1, playerStep):
            if not pathIsValid:
                break

            # Bounds check (1/2)
            if (i < 0 or width <= i):
                continue

            for j in range(y - playerSize, y + playerSize + 1, playerStep):

                # Bounds check (2/2)
                if (j < 0 or height <= j):
                    continue

                color = _stringify(pixels[i, j])
                if color == wallColor:
                    pathIsValid = False
                    break
        if not pathIsValid:
            continue

        # Base case 2: hit a different color
        color = _stringify(pixels[x, y])
        if color != roomColor and color in roomNames:
            continue

        # Base case 3: hit goal
        if vecLen(coord, end) <= stepSize:
            pathFound = True
            break

        # Iterative case
        for mx in range(-1, 2):
            for my in range(-1, 2):

                # Skip identical pixels
                if (mx == 0) and (my == 0):
                    continue

                px = x + mx * stepSize
                py = y + my * stepSize

                # Skip out of bounds pixels
                if (px < 0 or width <= px or py < 0 or height <= py):
                    continue

                # Skip visited pixels
                nextCoord = (px, py)
                travelled = float(node[1]) + vecLen((0,0), (stepSize*mx, stepSize*my))
                if not seen.get(nextCoord, None):
                    # Add pixel to queue
                    seen[nextCoord] = (coord, travelled, False)
                    dist = float(travelled) + _heuristic(nextCoord, end)
                    nodeQueue.put((dist, travelled, px, py))
                elif not seen[nextCoord][2] and seen[nextCoord][1] > travelled:
                    seen[nextCoord] = (coord, travelled, False)
                    dist = float(travelled) + _heuristic(nextCoord, end)
                    nodeQueue.put((dist, travelled, px, py))

    # Backtrack to start (if possible)
    if not pathFound:
        print "\033[91mDEST NOT REACHED " + str(start) + " --> " + str(end) + "\033[0m"
        return None

    path = list()
    if coord != end:
        path.append(end)
    while coord != start:
        path.append(coord)
        coord = seen[coord][0]

    return path
Esempio n. 4
0
def _findClosestPixel(inX, inY, targetColor, pixels, imgSize, searchRadius, stepSize=1):

    start = (inX, inY)

    # Queues
    coordQueue = Queue.Queue()
    coordQueue.put(start)

    width = imgSize[0]
    height = imgSize[1]

    # Visited
    visited = dict()
    visited[start] = True

    # Search
    while not coordQueue.empty():

        coord = coordQueue.get()

        x = coord[0]
        y = coord[1]

        # Base case 1: hit target
        curColor = _stringify(pixels[x, y])
        if curColor == targetColor:
            return coord

        # Base case 2: out of search range
        if vecLen(coord, start) > searchRadius:
            continue

        # Iterative case 1: further iteration (basically recursion)
        for mx in range(-1, 2):

            px = x + mx * stepSize

            # Skip out of bounds pixels (pt 1/2)
            if (px < 0 or width <= px):
                continue

            for my in range(-1, 2):

                # Skip identical pixels
                if (mx == 0) and (my == 0):
                    continue

                py = y + my * stepSize

                # Skip out of bounds pixels (pt 2/2)
                if (py < 0 or height <= py):
                    continue

                # Add pixel to queue
                nextPos = (px, py)
                if not visited.get(nextPos, False):
                    visited[nextPos] = True
                    coordQueue.put((px, py))

    # No match found
    return None
Esempio n. 5
0
    def turn(self, turn=None):
        while self.running and self.update_state(json.loads(turn)):

            # Get paths
            for p in self.people:
                p.path = []
                if p.pos != p.targetPos:
                    (p.path, p.waypoints) = self.construct_path(p.pos, p.targetPos)
                    p.pathLength = len(p.path)

            # Smooth moving
            turns = float(self.constants["TURN_FRAMES"])
            movementFinalized = False
            while turns >= 0 or not movementFinalized:
                movementFinalized = self.movementIsComplete()

                self.draw()
                self.update()
                self.GameClock.tick(self.MAX_FPS)

                turns -= 1.0

                for p in self.people:

                    # Calculate path length
                    iterSteps = float(p.pathLength) / float(self.constants["TURN_FRAMES"]) # Initial float
                    iterSteps = math.ceil(turns * iterSteps) - math.floor((turns - 1) * iterSteps) # Smooth float part out over turns
                    if p.path and len(p.path) > iterSteps:

                        for i in range(0, int(iterSteps)):
                            p.pos = p.path[0]
                            p.path.pop(0)

                        # Adjust rotation
                        rotationLookahead = int(self.constants["ROTATION_LOOKAHEAD"])
                        if len(p.path) > rotationLookahead:
                            p.set_rotation(angleBetween(p.pos, p.path[rotationLookahead]) - 90)
                        else:
                            p.set_rotation(angleBetween(p.pos, p.targetPos) - 90)

                    else:
                        p.pos = p.targetPos

                        # Check for direction marker, otherwise just keep current rotation
                        rotated = False
                        for d in self.rooms[p.room].dirmarkers:
                            if not rotated and vecLen(d, p.pos) < self.constants["DIR_MARKER_RADIUS"]:
                                p.set_rotation(angleBetween(p.pos, d) - 90)
                                rotated = True


                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        self.running = False
                        movementFinalized = True
            if self.running:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        self.running = False
            if not self.game_done:
                break
Esempio n. 6
0
    def construct_path(self, start, end):
        #print "construct paths " + str(start) + " --> " + str(end)
        # Rooms the path can go through
        allowedRooms = list(self.waypointRooms[start] | self.waypointRooms[end])

        # Queue of paths so far
        frontierPaths = Queue.PriorityQueue()
        frontierPaths.put([0, [start], 0])

        # Dict of points reached so far (to keep contains() at O(1))
        visited = dict()
        visited[start] = True

        while not frontierPaths.empty():

            currentNode = frontierPaths.get()
            currentPath = currentNode[1]  # A list of waypoints
            
            # Check if we've reached the goal - if so, terminate pathfinding
            currentWaypoint = currentPath[-1]
            if currentWaypoint == end:

                # Concatenate all the steps between the waypoints together
                currentSteps = []
                for i in range(0, len(currentPath) - 1):

                    a = currentPath[i+1]
                    b = currentPath[i]

                    fullPath = self.allPaths[a][b]
                    currentSteps.extend(fullPath)

                #print '-- Done --'
                return (currentSteps, currentPath)

            # Expand it
            for nextWaypoint in self.availableConnections[currentWaypoint]:

                # Don't include already-visited points
                if nextWaypoint in visited:
                    continue

                # Don't include waypoints in non-allowed rooms
                inAllowedRooms = False
                for r in self.waypointRooms[nextWaypoint]:
                    if r in allowedRooms:
                        inAllowedRooms = True
                        break
                if not inAllowedRooms:
                    continue

                # Mark next waypoint as visited
                visited[nextWaypoint] = True

                # Add path to frontier
                travelled = currentNode[2] + len(self.allPaths[nextWaypoint][currentWaypoint]) * self.mapConstants["path_step_size"]
                dist = vecLen(end, nextWaypoint)
                frontierPaths.put([travelled + dist, currentPath + [nextWaypoint], travelled])

        # No paths found
        #print '\033[91mERROR at construct_path: no path found between ' + str(start) + ' --> ' + str(end) + '\033[0m'
        return ([], [])
Esempio n. 7
0
def _findClosestPixel(inX,
                      inY,
                      targetColor,
                      pixels,
                      imgSize,
                      searchRadius,
                      stepSize=1):

    start = (inX, inY)

    # Queues
    coordQueue = Queue.Queue()
    coordQueue.put(start)

    width = imgSize[0]
    height = imgSize[1]

    # Visited
    visited = dict()
    visited[start] = True

    # Search
    while not coordQueue.empty():

        coord = coordQueue.get()

        x = coord[0]
        y = coord[1]

        # Base case 1: hit target
        curColor = _stringify(pixels[x, y])
        if curColor == targetColor:
            return coord

        # Base case 2: out of search range
        if vecLen(coord, start) > searchRadius:
            continue

        # Iterative case 1: further iteration (basically recursion)
        for mx in range(-1, 2):

            px = x + mx * stepSize

            # Skip out of bounds pixels (pt 1/2)
            if (px < 0 or width <= px):
                continue

            for my in range(-1, 2):

                # Skip identical pixels
                if (mx == 0) and (my == 0):
                    continue

                py = y + my * stepSize

                # Skip out of bounds pixels (pt 2/2)
                if (py < 0 or height <= py):
                    continue

                # Add pixel to queue
                nextPos = (px, py)
                if not visited.get(nextPos, False):
                    visited[nextPos] = True
                    coordQueue.put((px, py))

    # No match found
    return None
Esempio n. 8
0
def _findShortestValidPath(start, end, roomColor, pixels, imgSize, stepSize=1):

    # Ace settings
    playerSize = 4  # Should be 12, use 4 for testing
    playerStep = 4

    # seen
    seen = dict()
    seen[(start[0], start[1])] = ((-1, -1), 0, False)

    # Queues
    nodeQueue = Queue.PriorityQueue()
    nodeQueue.put((0.0, 0.0, start[0], start[1]))

    width = imgSize[0]
    height = imgSize[1]

    # Do BFS
    pathFound = False
    node = None
    while not nodeQueue.empty():

        node = nodeQueue.get()
        coord = node[2:]
        seenval = seen[coord]
        seen[coord] = (seenval[0], seenval[1], True)

        x = coord[0]
        y = coord[1]

        # Base case 1: too close to a wall
        pathIsValid = True
        for i in range(x - playerSize, x + playerSize + 1, playerStep):
            if not pathIsValid:
                break

            # Bounds check (1/2)
            if (i < 0 or width <= i):
                continue

            for j in range(y - playerSize, y + playerSize + 1, playerStep):

                # Bounds check (2/2)
                if (j < 0 or height <= j):
                    continue

                color = _stringify(pixels[i, j])
                if color == wallColor:
                    pathIsValid = False
                    break
        if not pathIsValid:
            continue

        # Base case 2: hit a different color
        color = _stringify(pixels[x, y])
        if color != roomColor and color in roomNames:
            continue

        # Base case 3: hit goal
        if vecLen(coord, end) <= stepSize:
            pathFound = True
            break

        # Iterative case
        for mx in range(-1, 2):
            for my in range(-1, 2):

                # Skip identical pixels
                if (mx == 0) and (my == 0):
                    continue

                px = x + mx * stepSize
                py = y + my * stepSize

                # Skip out of bounds pixels
                if (px < 0 or width <= px or py < 0 or height <= py):
                    continue

                # Skip visited pixels
                nextCoord = (px, py)
                travelled = float(node[1]) + vecLen(
                    (0, 0), (stepSize * mx, stepSize * my))
                if not seen.get(nextCoord, None):
                    # Add pixel to queue
                    seen[nextCoord] = (coord, travelled, False)
                    dist = float(travelled) + _heuristic(nextCoord, end)
                    nodeQueue.put((dist, travelled, px, py))
                elif not seen[nextCoord][2] and seen[nextCoord][1] > travelled:
                    seen[nextCoord] = (coord, travelled, False)
                    dist = float(travelled) + _heuristic(nextCoord, end)
                    nodeQueue.put((dist, travelled, px, py))

    # Backtrack to start (if possible)
    if not pathFound:
        print "\033[91mDEST NOT REACHED " + str(start) + " --> " + str(
            end) + "\033[0m"
        return None

    path = list()
    if coord != end:
        path.append(end)
    while coord != start:
        path.append(coord)
        coord = seen[coord][0]

    return path
Esempio n. 9
0
def _findShortestValidPath(start, end, roomColor, pixels, imgSize, stepSize=1):

    # Ace settings
    playerSize = 4  # Should be 12, use 4 for testing
    playerStep = 4

    # Parent positions
    parents = dict()
    parents[(start[0], start[1])] = (-1, -1)

    # Visited
    visited = dict()

    # Queues
    nodeQueue = Queue.PriorityQueue()
    nodeQueue.put((0.0, 0.0, start[0], start[1], []))

    width = imgSize[0]
    height = imgSize[1]

    # Do BFS
    pathFound = False
    node = None
    while not nodeQueue.empty():

        node = nodeQueue.get()
        coord = node[2:4]

        # Skip visited nodes
        if visited.get(coord, False):
            continue
        visited[coord] = True

        x = coord[0]
        y = coord[1]

        # Base case 1: too close to a wall
        pathIsValid = True
        for i in range(x - playerSize, x + playerSize + 1, playerStep):
            if not pathIsValid:
                break

            # Bounds check (1/2)
            if (i < 0 or width <= i):
                continue

            for j in range(y - playerSize, y + playerSize + 1, playerStep):

                # Bounds check (2/2)
                if (j < 0 or height <= j):
                    continue

                color = _stringify(pixels[i, j])
                if color == wallColor:
                    pathIsValid = False
                    break
        if not pathIsValid:
            continue

        # Base case 2: hit a different color
        color = _stringify(pixels[x, y])
        if color != roomColor and color in roomNames:
            continue

        # Base case 3: hit goal
        if vecLen(coord, end) <= stepSize:
            pathFound = True
            break

        # Iterative case
        for mx in range(-1, 2):
            for my in range(-1, 2):

                # Skip identical pixels
                if (mx == 0) and (my == 0):
                    continue

                px = x + mx * stepSize
                py = y + my * stepSize

                # Skip out of bounds pixels
                if (px < 0 or width <= px or py < 0 or height <= py):
                    continue

                # Skip visited pixels
                nextCoord = (px, py)
                if visited.get(nextCoord, False):
                    continue

                # Add pixel to queue
                travelled = float(node[1]) + vecLen((0,0), (stepSize*mx, stepSize*my))
                dist = float(travelled) + vecLen(nextCoord, end) # <-- disable A* because bugs
                nodeQueue.put((dist, travelled, px, py, [nextCoord] + node[4]))

    # Backtrack to start (if possible)
    if not pathFound:
        print "\033[91mDEST NOT REACHED " + str(start) + " --> " + str(end) + "\033[0m"
        return None

    path = node[4]

    return path