diff --git a/.idea/misc.xml b/.idea/misc.xml index d56657a..3fc3916 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/main.py b/main.py index f8a9a7f..364a80e 100644 --- a/main.py +++ b/main.py @@ -19,18 +19,11 @@ def main(): screen = pygame.display.set_mode((settings.screen_width, settings.screen_height)) pygame.display.set_caption('TRAKTOHOLIK') - paths = [] - goals = [(6, 2), (3,3), (4,1), (6, 2), (3, 8), (1, 7), (8, 1)] - startCords = (8, 1) - endCords = goals.pop(0) - startDir = Constants.UP - for goal in goals: - path = BFSSearcher().search(startCords, endCords, startDir) - paths.append(path) - startCords = endCords - endCords = goal - startDir = tractor.curr_direction - + start_cords = (8, 1) + goals = [(3, 3), (7, 7), (0, 0)] + end_cords = goals[0] + start_dir = tractor.curr_direction + path = BFSSearcher().search(start_cords, end_cords, start_dir) run = True while run: @@ -39,22 +32,26 @@ def main(): world.draw_lines(screen) tractor.draw(screen) + # print(path) + for event in pygame.event.get(): if event.type == pygame.QUIT: run = False - if len(paths) !=0 : - if len(paths[0]) != 0: - action = paths[0].pop(0) - tractor.update(action) - # tractor.check_collision(obstacles) - else: - paths.pop(0) - print(paths) + if path: + action = path.pop(0) + tractor.update(action) + else: + if len(goals) > 1: + start_cord = goals.pop(0) + end_cords = goals[0] + start_dir = tractor.curr_direction + path = BFSSearcher().search(start_cord, end_cords, start_dir) + pygame.time.wait(settings.freeze_time) pygame.display.update() pygame.quit() if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/src/tractor.py b/src/tractor.py index 94abff1..4046428 100644 --- a/src/tractor.py +++ b/src/tractor.py @@ -1,5 +1,4 @@ import pygame -import math from pygame.sprite import Sprite from constants import Constants as C @@ -14,28 +13,28 @@ class Tractor(Sprite): self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y - self.curr_direction = [0, 1] # wektor w ukladzie wspolrzednych wskazujacy kierunek traktora + self.curr_direction = C.UP # wektor w ukladzie wspolrzednych wskazujacy kierunek traktora self.engine = engine self.fertilizer = fertilizer def turn_right(self): - if self.curr_direction == [0, 1]: - self.curr_direction = [1, 0] + if self.curr_direction == C.UP: + self.curr_direction = C.RIGHT self.image = pygame.transform.scale( pygame.image.load('assets/images/tractor/tractor-transparent-right.png'), (self.settings.tile_size, self.settings.tile_size)) - elif self.curr_direction == [1, 0]: - self.curr_direction = [0, -1] + elif self.curr_direction == C.RIGHT: + self.curr_direction = C.DOWN self.image = pygame.transform.scale( pygame.image.load('assets/images/tractor/tractor-transparent-down.png'), (self.settings.tile_size, self.settings.tile_size)) - elif self.curr_direction == [0, -1]: - self.curr_direction = [-1, 0] + elif self.curr_direction == C.DOWN: + self.curr_direction = C.LEFT self.image = pygame.transform.scale( pygame.image.load('assets/images/tractor/tractor-transparent-left.png'), (self.settings.tile_size, self.settings.tile_size)) - elif self.curr_direction == [-1, 0]: - self.curr_direction = [0, 1] + elif self.curr_direction == C.LEFT: + self.curr_direction = C.UP self.image = pygame.transform.scale( pygame.image.load('assets/images/tractor/tractor-transparent-up.png'), (self.settings.tile_size, self.settings.tile_size)) @@ -43,23 +42,23 @@ class Tractor(Sprite): pygame.time.wait(self.settings.freeze_time) # bez tego sie kreci jak hot-wheels def turn_left(self): - if self.curr_direction == [0, 1]: - self.curr_direction = [-1, 0] + if self.curr_direction == C.UP: + self.curr_direction = C.LEFT self.image = pygame.transform.scale( pygame.image.load('assets/images/tractor/tractor-transparent-left.png'), (self.settings.tile_size, self.settings.tile_size)) - elif self.curr_direction == [-1, 0]: - self.curr_direction = [0, -1] + elif self.curr_direction == C.LEFT: + self.curr_direction = C.DOWN self.image = pygame.transform.scale( pygame.image.load('assets/images/tractor/tractor-transparent-down.png'), (self.settings.tile_size, self.settings.tile_size)) - elif self.curr_direction == [0, -1]: - self.curr_direction = [1, 0] + elif self.curr_direction == C.DOWN: + self.curr_direction = C.RIGHT self.image = pygame.transform.scale( pygame.image.load('assets/images/tractor/tractor-transparent-right.png'), (self.settings.tile_size, self.settings.tile_size)) - elif self.curr_direction == [1, 0]: - self.curr_direction = [0, 1] + elif self.curr_direction == C.RIGHT: + self.curr_direction = C.UP self.image = pygame.transform.scale( pygame.image.load('assets/images/tractor/tractor-transparent-up.png'), (self.settings.tile_size, self.settings.tile_size)) @@ -96,7 +95,6 @@ class Tractor(Sprite): self.turn_left() elif action == C.MOVE: self.move() - # print(self.rect) def draw(self, screen): screen.blit(self.image, self.rect) diff --git a/src/utils/bfs.py b/src/utils/bfs.py index 05e1e93..6848abd 100644 --- a/src/utils/bfs.py +++ b/src/utils/bfs.py @@ -11,70 +11,36 @@ class Node: self.agent_direction = agent_direction def successor(self): + actions = [] x = self.current_x y = self.current_y - actions = None - neighbours = [] - if x < 9: # right neighbour - if self.agent_direction == C.RIGHT: - actions = C.MOVE - elif self.agent_direction == C.LEFT: - actions = [C.ROTATE_RIGHT, C.ROTATE_RIGHT, C.MOVE] - elif self.agent_direction == C.UP: - actions = [C.ROTATE_RIGHT, C.MOVE] - elif self.agent_direction == C.DOWN: - actions = [C.ROTATE_LEFT, C.MOVE] + # vector rotation: https://stackoverflow.com/questions/4780119/2d-euclidean-vector-rotations + temp_direction = self.agent_direction + temp_direction = [-temp_direction[1], temp_direction[0]] + actions.append((C.ROTATE_LEFT, ((x, y), temp_direction))) - neighbours.append((actions, (x + 1, y), C.RIGHT)) + temp_direction = self.agent_direction + temp_direction = [temp_direction[1], -temp_direction[0]] + actions.append((C.ROTATE_RIGHT, ((x, y), temp_direction))) - if x > 0: # left neighbour - if self.agent_direction == C.RIGHT: - actions = [C.ROTATE_LEFT, C.ROTATE_LEFT, C.MOVE] - elif self.agent_direction == C.LEFT: - actions = C.MOVE - elif self.agent_direction == C.UP: - actions = [C.ROTATE_LEFT, C.MOVE] - elif self.agent_direction == C.DOWN: - actions = [C.ROTATE_RIGHT, C.MOVE] + if self.agent_direction == C.RIGHT and x < 9: + actions.append((C.MOVE, ((x + 1, y), self.agent_direction))) + elif self.agent_direction == C.LEFT and x > 0: + actions.append((C.MOVE, ((x - 1, y), self.agent_direction))) + elif self.agent_direction == C.UP and y < 9: + actions.append((C.MOVE, ((x, y + 1), self.agent_direction))) + elif self.agent_direction == C.DOWN and y > 0: + actions.append((C.MOVE, ((x, y - 1), self.agent_direction))) - neighbours.append((actions, (x - 1, y), C.LEFT)) - - if y < 9: # upper neighbour - if self.agent_direction == C.RIGHT: - actions = [C.ROTATE_LEFT, C.MOVE] - elif self.agent_direction == C.LEFT: - actions = [C.ROTATE_RIGHT, C.MOVE] - elif self.agent_direction == C.UP: - actions = C.MOVE - elif self.agent_direction == C.DOWN: - actions = [C.ROTATE_LEFT, C.ROTATE_LEFT, C.MOVE] - - neighbours.append((actions, (x, y + 1), C.UP)) - - if y > 0: # down neighbour - if self.agent_direction == C.RIGHT: - actions = [C.ROTATE_RIGHT, C.MOVE] - elif self.agent_direction == C.LEFT: - actions = [C.ROTATE_LEFT, C.MOVE] - elif self.agent_direction == C.UP: - actions = [C.ROTATE_LEFT, C.ROTATE_LEFT, C.MOVE] - elif self.agent_direction == C.DOWN: - actions = C.MOVE - - neighbours.append((actions, (x, y - 1), C.DOWN)) - return neighbours - - def __str__(self): - return self.state + ' ' + self.parent + return actions class BFSSearcher: def __init__(self): self.fringe = [] - self.explored_states = [] - self.path = [] + self.explored = [] def search(self, first_state: tuple, goal: tuple, agent_direction: list): self.fringe.append(Node(first_state[0], first_state[1], agent_direction)) @@ -85,29 +51,25 @@ class BFSSearcher: element: Node = self.fringe.pop(0) if element.state == goal: + # print(self.__state_eq_goal_action(element)) return self.__state_eq_goal_action(element) - self.explored_states.append(element) - for action, state, direction in element.successor(): - fringe_states = [] - explored_states = [] - for node in self.fringe: - fringe_states.append(node.state) - for node in self.explored_states: - explored_states.append(node.state) + self.explored.append(element) + + # print('state: ' + str(element.state) + ', direction: ' + str(element.agent_direction)) + # print(element.successor()) + + for action, state in element.successor(): + fringe_states = [(node.state, node.agent_direction) for node in self.fringe] + explored_states = [(node.state, node.agent_direction) for node in self.explored] if (state not in fringe_states) and (state not in explored_states): - x = Node(state[0], state[1], direction, action, element) + x = Node(state[0][0], state[0][1], state[1], action, element) self.fringe.append(x) - def __state_eq_goal_action(self, current_element: Node): - while current_element.parent: - if type(current_element.action) == list: - current_element.action.reverse() - for action in current_element.action: - self.path.append(action) - else: - self.path.append(current_element.action) - current_element = current_element.parent - - self.path.reverse() - return self.path + def __state_eq_goal_action(self, elem: Node): + path = [] + while elem.parent: + path.append(elem.action) + elem = elem.parent + path.reverse() + return path