commit 21b2510a4f8ee9ad4f2c5530cc030c47369637dd Author: HelQ Date: Fri Jun 3 02:50:23 2022 +0200 Trash Truck with BFS diff --git a/images/grass.png b/images/grass.png new file mode 100644 index 0000000..274cb70 Binary files /dev/null and b/images/grass.png differ diff --git a/images/rock.png b/images/rock.png new file mode 100644 index 0000000..aa2653f Binary files /dev/null and b/images/rock.png differ diff --git a/images/truck.png b/images/truck.png new file mode 100644 index 0000000..948a0df Binary files /dev/null and b/images/truck.png differ diff --git a/images/truck_d.png b/images/truck_d.png new file mode 100644 index 0000000..f10816c Binary files /dev/null and b/images/truck_d.png differ diff --git a/images/truck_l.png b/images/truck_l.png new file mode 100644 index 0000000..fc16823 Binary files /dev/null and b/images/truck_l.png differ diff --git a/images/truck_u.png b/images/truck_u.png new file mode 100644 index 0000000..9d1590d Binary files /dev/null and b/images/truck_u.png differ diff --git a/images/water.png b/images/water.png new file mode 100644 index 0000000..daa06a6 Binary files /dev/null and b/images/water.png differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..8d14361 --- /dev/null +++ b/main.py @@ -0,0 +1,69 @@ +from collections import deque + +from path_algorithms.bfs import bfs +from truck import Truck +from surface import * + +RESOLUTION = 900 +SIZE = 60 + +# matrix for display +matrix = [[1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 3, 1, 2, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1], + [3, 3, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + ] +pygame.init() +screen = pygame.display.set_mode([RESOLUTION, RESOLUTION]) +truck = Truck(screen) +surface_list = [] +# x and y are swapped on display in pygame +for i in range(15): + for j in range(15): + if matrix[i][j] == 1: + surface_list.append(Grass(screen, j * 60, i * 60, 1)) + if matrix[i][j] == 2: + surface_list.append(Rock(screen, j * 60, i * 60, 2)) + if matrix[i][j] == 3: + surface_list.append(Water(screen, j * 60, i * 60, 3)) + +run = 1 +path = [] +while True: + pygame.time.delay(500) + + for i in surface_list: + i.draw_surface() + truck.draw_truck() + + if run == 1: + start = truck.state + direction = truck.direction + endpoint = (0, 5) + path = bfs(surface_list, endpoint).tree_search(deque(), start, direction) + print(path) + run = 0 + + if path: + action = path.pop(0) + if action == 'M': + truck.move() + else: + truck.change_direction(action) + + pygame.display.flip() + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + exit() diff --git a/path_algorithms/a_star.py b/path_algorithms/a_star.py new file mode 100644 index 0000000..b1e23e5 --- /dev/null +++ b/path_algorithms/a_star.py @@ -0,0 +1,112 @@ +def get_path(cond): + path = [] + while cond.parent: + path.append(cond.action) + cond = cond.parent + return list(reversed(path)) + + +class bfs: + def __init__(self, surface_list, endpoint): + self.surface_list = surface_list + self.endpoint = endpoint + + def goal_achieved(self, state): + return state == self.endpoint + + def limitation_check(self, x, y): + for surface in self.surface_list: + if (surface.weight == 1) and (surface.y/60 == x) and (surface.x/60 == y): + return True + return False + + def add_all_possibilities(self, current): + states = [] + if current.direction == 'L': + # when you look left and turn left + new_condition = condition(current.state, 'D') + new_condition.action = 'L' + states.append(new_condition) + # when you turn right + new_condition = condition(current.state, 'U') + new_condition.action = 'R' + states.append(new_condition) + # when you move + if self.limitation_check(current.state[0], current.state[1] - 1): + new_condition = condition((current.state[0], current.state[1] - 1), current.direction) + new_condition.action = 'M' + states.append(new_condition) + + if current.direction == 'U': + # when you look up and turn left + new_condition = condition(current.state, 'L') + new_condition.action = 'L' + states.append(new_condition) + # when you turn right + new_condition = condition(current.state, 'R') + new_condition.action = 'R' + states.append(new_condition) + # when you move + if self.limitation_check(current.state[0] - 1, current.state[1]): + new_condition = condition((current.state[0] - 1, current.state[1]), current.direction) + new_condition.action = 'M' + states.append(new_condition) + + if current.direction == 'R': + # when you look right and turn left + new_condition = condition(current.state, 'U') + new_condition.action = 'L' + states.append(new_condition) + # when you turn right + new_condition = condition(current.state, 'D') + new_condition.action = 'R' + states.append(new_condition) + # when you move + if self.limitation_check(current.state[0], current.state[1] + 1): + new_condition = condition((current.state[0], current.state[1] + 1), current.direction) + new_condition.action = 'M' + states.append(new_condition) + + if current.direction == 'D': + # when you look down and turn left + new_condition = condition(current.state, 'R') + new_condition.action = 'L' + states.append(new_condition) + # when you turn right + new_condition = condition(current.state, 'L') + new_condition.action = 'R' + states.append(new_condition) + # when you move + if self.limitation_check(current.state[0] + 1, current.state[1]): + new_condition = condition((current.state[0] + 1, current.state[1]), current.direction) + new_condition.action = 'M' + states.append(new_condition) + return states + + def tree_search(self, queue, start, direction): + queue.append(condition(start, direction)) + while queue: + elem = queue.popleft() + + if self.goal_achieved(elem.state): + return get_path(elem) + + for state in self.add_all_possibilities(elem): + if state not in queue: + state.parent = elem + queue.append(state) + + +class condition: + def __init__(self, state, direction): + self.state = state + self.parent = None + self.action = None + self.direction = direction + self.cost = 0 + + def __eq__(self, other): + if isinstance(other, condition): + return (self.state == other.state and + self.action == other.action and + self.direction == other.direction) diff --git a/path_algorithms/bfs.py b/path_algorithms/bfs.py new file mode 100644 index 0000000..c9e939a --- /dev/null +++ b/path_algorithms/bfs.py @@ -0,0 +1,111 @@ +def get_path(cond): + path = [] + while cond.parent: + path.append(cond.action) + cond = cond.parent + return list(reversed(path)) + + +class bfs: + def __init__(self, surface_list, endpoint): + self.surface_list = surface_list + self.endpoint = endpoint + + def goal_achieved(self, state): + return state == self.endpoint + + def limitation_check(self, x, y): + for surface in self.surface_list: + if (surface.weight == 1) and (surface.y/60 == x) and (surface.x/60 == y): + return True + return False + + def add_all_possibilities(self, current): + states = [] + if current.direction == 'L': + # when you look left and turn left + new_condition = condition(current.state, 'D') + new_condition.action = 'L' + states.append(new_condition) + # when you turn right + new_condition = condition(current.state, 'U') + new_condition.action = 'R' + states.append(new_condition) + # when you move + if self.limitation_check(current.state[0], current.state[1] - 1): + new_condition = condition((current.state[0], current.state[1] - 1), current.direction) + new_condition.action = 'M' + states.append(new_condition) + + if current.direction == 'U': + # when you look up and turn left + new_condition = condition(current.state, 'L') + new_condition.action = 'L' + states.append(new_condition) + # when you turn right + new_condition = condition(current.state, 'R') + new_condition.action = 'R' + states.append(new_condition) + # when you move + if self.limitation_check(current.state[0] - 1, current.state[1]): + new_condition = condition((current.state[0] - 1, current.state[1]), current.direction) + new_condition.action = 'M' + states.append(new_condition) + + if current.direction == 'R': + # when you look right and turn left + new_condition = condition(current.state, 'U') + new_condition.action = 'L' + states.append(new_condition) + # when you turn right + new_condition = condition(current.state, 'D') + new_condition.action = 'R' + states.append(new_condition) + # when you move + if self.limitation_check(current.state[0], current.state[1] + 1): + new_condition = condition((current.state[0], current.state[1] + 1), current.direction) + new_condition.action = 'M' + states.append(new_condition) + + if current.direction == 'D': + # when you look down and turn left + new_condition = condition(current.state, 'R') + new_condition.action = 'L' + states.append(new_condition) + # when you turn right + new_condition = condition(current.state, 'L') + new_condition.action = 'R' + states.append(new_condition) + # when you move + if self.limitation_check(current.state[0] + 1, current.state[1]): + new_condition = condition((current.state[0] + 1, current.state[1]), current.direction) + new_condition.action = 'M' + states.append(new_condition) + return states + + def tree_search(self, queue, start, direction): + queue.append(condition(start, direction)) + while queue: + elem = queue.popleft() + + if self.goal_achieved(elem.state): + return get_path(elem) + + for state in self.add_all_possibilities(elem): + if state not in queue: + state.parent = elem + queue.append(state) + + +class condition: + def __init__(self, state, direction): + self.state = state + self.parent = None + self.action = None + self.direction = direction + + def __eq__(self, other): + if isinstance(other, condition): + return (self.state == other.state and + self.action == other.action and + self.direction == other.direction) diff --git a/surface.py b/surface.py new file mode 100644 index 0000000..f7b5955 --- /dev/null +++ b/surface.py @@ -0,0 +1,38 @@ +import pygame + + +class Surface: + + def __init__(self, screen, x, y, weight): + self.state = (x, y) + self.x = x + self.y = y + self.weight = weight + self.screen = screen + self.image = pygame.image.load('images/grass.png') + self.surface_rect = self.image.get_rect() + self.surface_rect.center = (self.x + 30, self.y + 30) + + def draw_surface(self): + self.screen.blit(self.image, self.surface_rect) + + +class Grass(Surface): + + def __init__(self, screen, x, y, weight): + super().__init__(screen, x, y, weight) + self.image = pygame.image.load('images/grass.png') + + +class Rock(Surface): + + def __init__(self, screen, x, y, weight): + super().__init__(screen, x, y, weight) + self.image = pygame.image.load('images/rock.png') + + +class Water(Surface): + + def __init__(self, screen, x, y, weight): + super().__init__(screen, x, y, weight) + self.image = pygame.image.load('images/water.png') diff --git a/truck.py b/truck.py new file mode 100644 index 0000000..0b63d93 --- /dev/null +++ b/truck.py @@ -0,0 +1,82 @@ +import pygame + + +class Truck: + + def __init__(self, screen): + self.x = 0 + self.y = 0 + self.state = (self.x, self.y) + self.direction = 'R' + self.screen = screen + self.image = pygame.image.load('images/truck.png') + self.truck_rect = self.image.get_rect() + self.truck_rect.center = (self.x + 30, self.y + 30) + + def draw_truck(self): + self.screen.blit(self.image, self.truck_rect) + + def change_image(self): + if self.direction == 'R': + self.image = pygame.image.load('images/truck.png') + self.truck_rect = self.image.get_rect() + self.truck_rect.center = (self.x + 30, self.y + 30) + if self.direction == 'L': + self.image = pygame.image.load('images/truck_l.png') + self.truck_rect = self.image.get_rect() + self.truck_rect.center = (self.x + 30, self.y + 30) + if self.direction == 'U': + self.image = pygame.image.load('images/truck_u.png') + self.truck_rect = self.image.get_rect() + self.truck_rect.center = (self.x + 30, self.y + 30) + if self.direction == 'D': + self.image = pygame.image.load('images/truck_d.png') + self.truck_rect = self.image.get_rect() + self.truck_rect.center = (self.x + 30, self.y + 30) + + def change_direction(self, turn): + if turn == 'L': + if self.direction == 'R': + self.direction = 'U' + elif self.direction == 'U': + self.direction = 'L' + elif self.direction == 'L': + self.direction = 'D' + elif self.direction == 'D': + self.direction = 'R' + if turn == 'R': + if self.direction == 'R': + self.direction = 'D' + elif self.direction == 'U': + self.direction = 'R' + elif self.direction == 'L': + self.direction = 'U' + elif self.direction == 'D': + self.direction = 'L' + self.change_image() + + def move(self): + if self.direction == 'R': + self.move_right() + if self.direction == 'U': + self.move_up() + if self.direction == 'L': + self.move_left() + if self.direction == 'D': + self.move_down() + + def move_right(self): + self.x += 60 + self.truck_rect.center = (self.x + 30, self.y + 30) + + def move_left(self): + self.x -= 60 + self.truck_rect.center = (self.x + 30, self.y + 30) + + def move_up(self): + self.y -= 60 + self.truck_rect.center = (self.x + 30, self.y + 30) + + def move_down(self): + self.y += 60 + self.truck_rect.center = (self.x + 30, self.y + 30)