Example #1
0
    def __mapBlockSurrounding(self, block, blocks):
        """
        Maps the surrounding of the block given
        """
        encoded_map = bitmap.BitMap(8)  #8 Surrounding blocks
        total_walls = 0

        #Make list of all surrounding blocks in board
        bx, by = block
        surrounding = [
            (sur_x, sur_y)
            for sur_x in range(bx - self.size, bx + self.size * 2, self.size)
            for sur_y in range(by - self.size, by + self.size * 2, self.size)
            if sur_x != bx or sur_y != by
        ]

        #Encode the surroundings into the bitmap
        for index, (x, y) in enumerate(surrounding):
            if (snake.Block(self.size, x, y) in blocks or x <= self.leftBoundry
                    or y <= 0 or x >= self.rightBoundry
                    or y >= self.gameHeight):

                encoded_map.set(index)

        return encoded_map
Example #2
0
    def isSafe(self):
        """
        Determine if the food is in a reachable location

        OVERRIDE
        """
        return (super().isSafe() and snake.Block(self.width, self.x, self.y)
                not in self.game.redirection_blocks)
Example #3
0
    def __closest2Walls(self, block):
        """
        Returns the two closest walls to the given point on the grid
        """

        #Add error checking
        walls = [
            snake.Block(block.width, block.x, 0),
            snake.Block(block.width, self.leftBoundry, block.x),
            snake.Block(block.width, block.x, self.gameHeight),
            snake.Block(block.width, block.rightBoundry, block.y)
        ]

        distances = sorted(
            [self.__gridDistanceBetweenBlocks(block, x) for x in walls])

        return distances[:2]
Example #4
0
    def __blockSafety(self, block, blocks):
        """
        Examines if the block is safely placed
        """
        #Check blocks L R U and D from current block and enocde that area
        all_surroundings = [(block.x - block.width, block.y),
                            (block.x + block.width, block.y),
                            (block.x, block.y - block.width),
                            (block.x, block.y + block.width)]

        #Encode each surrounding
        for surrounding in all_surroundings:
            encoded_map = self.__mapBlockSurrounding(surrounding, blocks)
            #Check for conflict
            if encoded_map.count(
            ) >= 3:  #If it's less, theres no possibility of conflict
                #Check for -_- shape (impossible to escape)
                if ((encoded_map[3] and encoded_map[4] and
                     (encoded_map[1] or encoded_map[6]))
                        or ((encoded_map[1] and encoded_map[6]) and
                            (encoded_map[3] or encoded_map[4]))):
                    return False  #Not valid, conflict exists

        #Add the corners so we can find the edges
        #Doesn't get corners that don't exist (ie: "fake" corner)
        #   ### <- This   ##
        #   #  #         #  #
        #              ->   #
        #   #            # ##
        #                   #
        #  # #
        #
        #Thought: if we have 3 corners we can find the 4th
        corner_blocks = self.__addCorners(blocks)
        blocks_with_corners = blocks + corner_blocks

        #if len(blocks) >= 3:
        if False:  #This isn't working
            edges = self.__findEdges(blocks_with_corners)

            if len(edges) == 3:
                x_values = [x.x for x in edges]
                y_values = [x.y for x in edges]

                missing_x = [m for m in x_values if x_values.count(m) == 1]
                missing_y = [m for m in y_values if y_values.count(m) == 1]

                edges += [snake.Block(self.size, missing_x, missing_y)]

            elif len(edges) > 4:
                raise RunTimeError("More than 4 edges")
            elif len(edges) < 4:
                return True

            return self.__distanceInEdges(edges, blocks) < 2
        else:
            return True
Example #5
0
 def hitRedirect(self, newX, newY):
     """
     Checks if the move about to be made will collide with any of the blocks
     that will redirect the snake.
     """
     newBlock = snake.Block(self.width, newX, newY)
     for block in self.game.redirection_blocks:
         if block.colliderect(newBlock):
             self.hit_redirect = True
             break
Example #6
0
    def move(self):
        """
        Move the snake.

        The snake moves by shifting the entire array of the tail to the left (removing the last
        element) and putting a new Block where the head used to be. 
        """

        self.hit_self = False
        self.hit_wall = False
        self.hit_redirect = False

        if self.tail:
            self.tail = self.tail[1:]
            self.tail.append(snake.Block(self.game.size, self.x, self.y))
            for block in self.tail[1:]:
                block.resetColor()
            self.tail[0].color = (255, 250, 205)

        newY = self.dy + self.y
        newX = self.dx + self.x

        self.hitWall(newX, newY)
        if self.hit_wall:
            if self.game.noBoundry:
                self.__goThroughWall(newX, newY)
                self.checkEat(self.x, self.y)
            elif self.game.assist:
                self.assist()
            else:
                self.die()
            return

        self.hitRedirect(newX, newY)
        if self.hit_redirect:
            self.die()
            #self.assist(tail=True)
            #self.checkEat(self.x, self.y)
            #return

        if not self.checkEat(newX, newY):
            # Only check if the snake hits itself if it didn't eat,
            # eating causes another block to be placed exactly where the snake is
            self.hitSelf(newX, newY)
            if self.hit_self:
                if self.game.assist:
                    self.assist()
                else:
                    self.die()
                self.hit_self = False
                return  #Don't update the snake if bad move

        self.y = newY
        self.x = newX
Example #7
0
    def __encodeSurrounding(cls, bmap, minimum_value, snake_obj, bit_start=0):
        global redirection_blocks
        surrounding = cls.__mapSurrounding(snake_obj, minimum_value)
        encoded_map = bmap
        # Checks each block in the surrounding and checks if it is near a wall, or near a piece of the tail
        bit_position = bit_start
        for (index, (x, y, block)) in enumerate(surrounding):
            if index % minimum_value == 0 and index != 0:  # Don't increment immediately
                bit_position += 1

            if (x < snake_obj.game.leftBoundry or y < 0
                    or x == snake_obj.game.rightBoundry
                    or y == constant.WINDOW_HEIGHT
                    or snake.Block(snake_obj.width, x, y) in redirection_blocks
                    or
                (block != None
                 and block.colliderect(snake.Block(constant.BLOCK_SIZE, x, y)))
                    and not encoded_map.test(bit_position)):

                encoded_map.set(bit_position)
Example #8
0
    def __distanceInEdges(self, edges, blocks):
        sorted_edges = sorted(edges, key=lambda e: (e.x, e.y))
        same_x = [[sorted_edges[:2]], [sorted_edges[2:]]]
        same_y = [[sorted_edges[::2]], [sorted_edges[1::1]]]

        total_distance = 0
        distance_between_x = self.__gridDistanceBetweenBlocks(*same_x)
        for x in range(distance_between_x):
            check_block = snake.Block(x.width, same_x[0].x + x * self.size,
                                      same_x[1])
            if check_block not in blocks:
                total_distance += 1

        distance_between_y = self.__gridDistanceBetweenBlocks(*same_y)
        for y in range(distance_between_y):
            check_block = snake.Block(x.width, same_x[0].x,
                                      same_x[1] + y * self.size)
            if check_block not in blocks:
                total_distance += 1

        return total_distance
Example #9
0
    def __touchingOtherBlock(self, block, blocks):
        """
        Retruns a list of blocks that are touching the given block

        Argument List:
        blocks - List of blocks on the board
        """
        directions = [
            snake.Direction.UP, snake.Direction.DOWN, snake.Direction.LEFT,
            snake.Direction.RIGHT
        ]

        blocks_touching = []
        for direction in directions:
            dx, dy = map(lambda x: x * block.width, direction.value)
            newBlock = snake.Block(block.width, block.x + block.dx,
                                   block.y + block.dy)
            if newBlock in blocks:
                blocks_touching += [newBlock]

        return blocks_touching
Example #10
0
    def __createBlocks(self):
        """
        Creates the blocks that will push away and place them on the baord.

        TODO: Place the blocks, randomly, but check that they don't limit an
        area? Or place the blocks in the same place every time?
        """
        block_coordinates = []
        for i in range(10):
            safe = False
            while not safe:
                block_coordinates.append(
                    snake.Block(self.size,
                                random.randint(self.leftBoundry / self.size,
                                               self.rows) * self.size,
                                random.randint(0, self.cols) * self.size,
                                color=(220, 220, 220)))

                if self.__isSafe(block_coordinates):
                    safe = True
                else:
                    block_coordinates.pop()

        return block_coordinates
Example #11
0
    def __searchEdge(self,
                     origin,
                     blocks,
                     last_direction=None,
                     block=None,
                     distance_travelled=0):

        if block == origin:
            return True

        if distance_travelled >= 2:
            return block

        if block == None:
            block = origin

        directions = [
            snake.Direction.UP, snake.Direction.DOWN, snake.Direction.LEFT,
            snake.Direction.RIGHT
        ]

        if last_direction:  #We won't undo the last move
            directions.remove(~last_direction)

        for direction in directions:
            dx, dy = map(lambda x: x * block.width, direction.value)
            newBlock = snake.Block(block.width, block.x + dx, block.y + dy)

            if newBlock in blocks:
                further = self.__searchEdge(origin, blocks, direction,
                                            newBlock, distance_travelled)
            else:
                further = self.__searchEdge(origin, blocks, direction,
                                            newBlock, distance_travelled + 1)

        return False
Example #12
0
    def __addCorners(self, blocks):
        temp_blocks = []
        for block in blocks:
            # We have to take into account the new blocks we have added so we
            # Don't double add
            encoded_map = self.__mapBlockSurrounding((block.x, block.y),
                                                     blocks + temp_blocks)
            if encoded_map[1] and encoded_map[3] and not encoded_map[0]:
                temp_blocks += [
                    snake.Block(block.width, block.x - block.width,
                                block.y - block.width)
                ]
                encoded_map.set(0)

            if encoded_map[1] and encoded_map[4] and not encoded_map[3]:
                temp_blocks += [
                    snake.Block(block.width, block.x - block.width,
                                block.y + block.width)
                ]
                encoded_map.set(3)

            if encoded_map[6] and encoded_map[3] and not encoded_map[5]:
                temp_blocks += [
                    snake.Block(block.width, block.x + block.width,
                                block.y - block.width)
                ]
                encoded_map.set(5)

            if encoded_map[6] and encoded_map[4] and not encoded_map[7]:
                temp_blocks += [
                    snake.Block(block.width, block.x + block.width,
                                block.y + block.width)
                ]
                encoded_map.set(7)

            if encoded_map[0]:
                if not encoded_map[1]:
                    temp_blocks += [
                        snake.Block(block.width, block.x - block.width,
                                    block.y)
                    ]
                    encoded_map.set(1)

                if not encoded_map[3]:
                    temp_blocks += [
                        snake.Block(block.width, block.x,
                                    block.y - block.width)
                    ]
                    encoded_map.set(3)

            if encoded_map[2]:
                if not encoded_map[1]:
                    temp_blocks += [
                        snake.Block(block.width, block.x - block.width,
                                    block.y)
                    ]
                    encoded_map.set(1)

                if not encoded_map[4]:
                    temp_blocks += [
                        snake.Block(block.width, block.x,
                                    block.width + block.y)
                    ]
                    encoded_map.set(4)

            if encoded_map[5]:
                if not encoded_map[3]:
                    temp_blocks += [
                        snake.Block(block.width, block.x,
                                    block.y - block.width)
                    ]
                    encoded_map.set(3)

                if not encoded_map[6]:
                    temp_blocks += [
                        snake.Block(block.width, block.x + block.width,
                                    block.y)
                    ]
                    encoded_map.set(6)

            if encoded_map[7]:
                if not encoded_map[4]:
                    temp_blocks += [
                        snake.Block(block.width, block.x,
                                    block.width + block.y)
                    ]

                if not encoded_map[6]:
                    temp_blocks += [
                        snake.Block(block.width, block.x + block.width,
                                    block.y)
                    ]
                    encoded_map.set(6)

        return temp_blocks