Trash Truck with BFS
BIN
images/grass.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
images/rock.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
images/truck.png
Normal file
After Width: | Height: | Size: 861 B |
BIN
images/truck_d.png
Normal file
After Width: | Height: | Size: 894 B |
BIN
images/truck_l.png
Normal file
After Width: | Height: | Size: 880 B |
BIN
images/truck_u.png
Normal file
After Width: | Height: | Size: 897 B |
BIN
images/water.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
69
main.py
Normal file
@ -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()
|
112
path_algorithms/a_star.py
Normal file
@ -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)
|
111
path_algorithms/bfs.py
Normal file
@ -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)
|
38
surface.py
Normal file
@ -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')
|
82
truck.py
Normal file
@ -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)
|