Advertisement
Cpt_Jellyfish

EEEE4008: Host Machine Python Code

May 13th, 2021
666
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.39 KB | None | 0 0
  1. #import libraries and functions
  2. import pygame
  3. import math
  4. from queue import PriorityQueue
  5. from itertools import cycle
  6. import io
  7. import dropbox
  8.  
  9. #delete token when uploading
  10. token = "" #add your own dropbox API token here
  11. DBX = dropbox.Dropbox(token)
  12.  
  13. #setup the window
  14. ROWS = 21
  15. WIDTH = 16*ROWS
  16. WIN = pygame.display.set_mode((WIDTH, WIDTH))
  17. pygame.display.set_caption("A* Path Finding Algorithm within a Maze")
  18.  
  19. #define global variables
  20. global poolNext
  21. poolNext = [3,0,1,2]
  22. poolNext = cycle(poolNext)
  23.  
  24. #define colour codes in RGB format
  25. RED = (255, 0, 0)
  26. GREEN = (0, 255, 0)
  27. BLUE = (0, 255, 0)
  28. YELLOW = (255, 255, 0)
  29. WHITE = (255, 255, 255)
  30. BLACK = (0, 0, 0)
  31. PURPLE = (128, 0, 128)
  32. ORANGE = (255, 165 ,0)
  33. GREY = (128, 128, 128)
  34. TURQUOISE = (64, 224, 208)
  35.  
  36. #define the Spot class - each spot is a cell
  37. class Spot:
  38.         #define each spots default parameters - default to black (obstacle)
  39.     def __init__(self, row, col, width, total_rows):
  40.         self.row = row
  41.         self.col = col
  42.         self.x = row * width
  43.         self.y = col * width
  44.         self.colour = BLACK
  45.         self.neighbours = []
  46.         self.width = width
  47.         self.total_rows = total_rows
  48.  
  49.     def get_pos(self):
  50.         return self.row, self.col
  51.  
  52.     def is_closed(self):
  53.         return self.colour == RED
  54.  
  55.     def is_open(self):
  56.         return self.colour == GREEN
  57.  
  58.     def is_barrier(self):
  59.         return self.colour == BLACK
  60.  
  61.     def is_start(self):
  62.         return self.colour == ORANGE
  63.  
  64.     def is_end(self):
  65.         return self.colour == TURQUOISE
  66.  
  67.     def draw_path(self):
  68.         self.colour = WHITE
  69.  
  70.     def make_start(self):
  71.         self.colour = ORANGE
  72.  
  73.     def make_closed(self):
  74.         self.colour = RED
  75.  
  76.     def make_open(self):
  77.         self.colour = GREEN
  78.  
  79.     def make_barrier(self):
  80.         self.colour = BLACK
  81.  
  82.     def make_end(self):
  83.         self.colour = TURQUOISE
  84.  
  85.     def draw_shortest_path(self):
  86.         self.colour = PURPLE
  87.  
  88.     def draw(self, win):
  89.         pygame.draw.rect(win, self.colour, (self.x, self.y, self.width, self.width))
  90.  
  91.         #define the neighbours indexes to a specific cell
  92.     def update_neighbours(self, grid):
  93.         self.neighbours = []
  94.         if self.row < self.total_rows - 1 and not grid[self.row + 1][self.col].is_barrier(): #down    
  95.             self.neighbours.append(grid[self.row + 1][self.col])
  96.  
  97.         if self.row > 0 and not grid[self.row - 1][self.col].is_barrier(): #up
  98.             self.neighbours.append(grid[self.row - 1][self.col])
  99.  
  100.         if self.col < self.total_rows - 1 and not grid[self.row][self.col + 1].is_barrier(): #right
  101.             self.neighbours.append(grid[self.row][self.col + 1])
  102.  
  103.         if self.col > 0 and not grid[self.row][self.col - 1].is_barrier(): #left
  104.             self.neighbours.append(grid[self.row][self.col - 1])
  105.  
  106.     def __lt__(self, other):
  107.         return False
  108.  
  109. #define the manhattan distance heuristic
  110. def heuristic(p1, p2):
  111.     x1, y1 = p1
  112.     x2, y2 = p2
  113.     return abs(x1 - x2) + abs(y1 - y2)
  114.  
  115. #define the shortest path visualisation
  116. def reconstruct_path(came_from, current, draw):
  117.     while current in came_from:
  118.         current = came_from[current]
  119.         current.draw_shortest_path()
  120.         draw()
  121.  
  122. #define the A-star algorithm
  123. def algorithm(draw, grid, start, end):
  124.     count = 0
  125.     open_set = PriorityQueue()
  126.     open_set.put((0, count, start))
  127.     came_from = {}
  128.     g_score = {spot: float("inf") for row in grid for spot in row}
  129.     g_score[start] = 0
  130.     f_score = {spot: float("inf") for row in grid for spot in row}
  131.     f_score[start] = heuristic(start.get_pos(), end.get_pos())
  132.  
  133.     open_set_hash = {start}
  134.  
  135.         #when not at the end node or whole maze not explored
  136.     while not open_set.empty():
  137.                 #if the close button is pressed
  138.         for event in pygame.event.get():
  139.             if event.type == pygame.QUIT:
  140.                 pygame.quit()
  141.  
  142.         current = open_set.get()[2]
  143.         open_set_hash.remove(current)
  144.  
  145.                 #once at the end node
  146.         if current == end:
  147.             reconstruct_path(came_from, end, draw)
  148.             end.make_end()
  149.             return True
  150.  
  151.                 #for each of the neighbours, calculate and select the one with the lowest manhattan distance
  152.         for neighbour in current.neighbours:
  153.             temp_g_score = g_score[current] + 1
  154.  
  155.             if temp_g_score < g_score[neighbour]:
  156.                 came_from[neighbour] = current
  157.                 g_score[neighbour] = temp_g_score
  158.                 f_score[neighbour] = temp_g_score + heuristic(neighbour.get_pos(), end.get_pos())
  159.                 if neighbour not in open_set_hash:
  160.                     count += 1
  161.                     open_set.put((f_score[neighbour], count, neighbour))
  162.                     open_set_hash.add(neighbour)
  163.                     neighbour.make_open()
  164.  
  165.         draw()
  166.  
  167.         if current != start:
  168.             current.make_closed()
  169.  
  170.     return False
  171.  
  172. #define the grid generation parameters
  173. def make_grid(rows, width):
  174.     grid = []
  175.     gap = width // rows
  176.     for i in range(rows):
  177.         grid.append([])
  178.         for j in range(rows):
  179.             spot = Spot(i, j, gap, rows)
  180.             grid[i].append(spot)
  181.  
  182.     return grid
  183.  
  184. #define the gridline parameters
  185. def draw_grid(win, rows, width):
  186.     gap = width // rows
  187.     for i in range(rows):
  188.         pygame.draw.line(win, GREY, (0, i * gap), (width, i * gap))
  189.         for j in range(rows):
  190.             pygame.draw.line(win, GREY, (j * gap, 0), (j * gap, width))
  191.  
  192. #define the update to the whole window
  193. def draw(win, grid, rows, width):
  194.     win.fill(WHITE)
  195.  
  196.     for row in grid:
  197.         for spot in row:
  198.             spot.draw(win)
  199.  
  200.     draw_grid(win, rows, width)
  201.     pygame.display.update() #update the pygame window
  202.  
  203. #define the main function
  204. def main(win, width, ROWS):
  205.         #make the initial grid full of obstacles
  206.     grid = make_grid(ROWS, width)
  207.  
  208.                 #path = 'C:/Users/natda/Desktop/maze.txt'
  209.     _, res = DBX.files_download("/maze.txt")
  210.     res.raise_for_status()
  211.  
  212.     with io.BytesIO(res.content) as stream:
  213.         temp = stream.read().decode()
  214.            
  215.                 #maze_file = open(path,'r')
  216.                 #temp = maze_file.read()
  217.     maze_path = temp.split(',')     #seperate string at commas
  218.     length = len(maze_path)
  219.  
  220.     #mark start
  221.     start = grid[int(ROWS/2)][ROWS-1]
  222.     start.make_start()
  223.  
  224.     #set current position as start point
  225.     current_x = int(ROWS/2)
  226.     current_y = ROWS - 1
  227.  
  228.     #draw inital forward motion
  229.     step_total = int(maze_path[0])
  230.     for step in range(1,step_total):
  231.         path = grid[current_x][current_y - step]
  232.         path.draw_path()
  233.  
  234.     #update current position
  235.     current_y = current_y - step
  236.  
  237.     #draw all paths
  238.     for i in range(1,length):
  239.         #print (maze_path[i])
  240.         path_var = maze_path[i]
  241.  
  242.         if path_var == 'L':
  243.             #print ("Turn")
  244.             dirFlag = next(poolNext)
  245.             dirFlag = next(poolNext)
  246.             dirFlag = next(poolNext)
  247.             #print("Q: " + str(dirFlag))
  248.         elif path_var == 'R':
  249.             dirFlag = next(poolNext)
  250.             #print("Q: " + str(dirFlag))
  251.         else :
  252.             if dirFlag == 0 or dirFlag == 4:
  253.                 #draw down
  254.                 path_var = int(path_var)+1
  255.                 for step in range(1,path_var):
  256.                     path = grid[current_x][current_y + step]
  257.                     path.draw_path()
  258.                     draw(WIN, grid, ROWS, WIDTH)
  259.                 current_y = current_y + step
  260.             if dirFlag == 1:
  261.                 #draw left
  262.                 path_var = int(path_var)+1
  263.                 for step in range(1,path_var):
  264.                     path = grid[current_x - step][current_y]
  265.                     path.draw_path()
  266.                     draw(WIN, grid, ROWS, WIDTH)
  267.                 current_x = current_x - step
  268.             if dirFlag == 2:
  269.                 #draw up
  270.                 path_var = int(path_var)+1
  271.                 for step in range(1,path_var):
  272.                     path = grid[current_x][current_y - step]
  273.                     path.draw_path()
  274.                     draw(WIN, grid, ROWS, WIDTH)
  275.                 current_y = current_y - step
  276.             if dirFlag == 3:
  277.                 #draw right
  278.                 path_var = int(path_var)+1
  279.                 for step in range(1,path_var):
  280.                     path = grid[current_x + step][current_y]
  281.                     path.draw_path()
  282.                     draw(WIN, grid, ROWS, WIDTH)
  283.                 current_x = current_x + step
  284.                
  285.  
  286.     #print("X: " + str(current_x))
  287.     #print("Y: " + str(current_y))
  288.  
  289.     #mark end
  290.     end = grid[current_x][current_y]
  291.     end.make_end()
  292.    
  293.     run = True
  294.     while run:
  295.         draw(win, grid, ROWS, width)
  296.         #if the close button is pressed
  297.         for event in pygame.event.get():
  298.             if event.type == pygame.QUIT:
  299.                 run = False
  300.  
  301.             #if the spacebar pressed - start algorithm
  302.             if event.type == pygame.KEYDOWN:
  303.                 if event.key == pygame.K_SPACE:
  304.                     for row in grid:
  305.                         for spot in row:
  306.                             spot.update_neighbours(grid)
  307.  
  308.                     algorithm(lambda: draw(win, grid, ROWS, width), grid, start, end)
  309.                    
  310.                                         ##start shortest path extraction
  311.                     #open & clear text file
  312.                     path2 = 'C:/Users/natda/Desktop/extracted_route.txt'
  313.                     extracted_route = open(path2,'w') #w overwrites existing file
  314.                    
  315.                     #extract route
  316.                     current_x = int(ROWS/2)
  317.                     current_y = ROWS - 1
  318.                     current_pos = grid[current_x][current_y]
  319.                     route_string = ""
  320.                     prev_move = ''
  321.  
  322.                     neighbour_up = grid[current_x][current_y - 1]
  323.                     neighbour_left = grid[current_x - 1][current_y]
  324.                     neighbour_right = grid[current_x + 1][current_y]
  325.  
  326.                     if neighbour_up.colour == PURPLE:
  327.                         prev_move = 'U'
  328.                         route_string += "U"
  329.                         current_y = current_y - 1
  330.                        
  331.                     if neighbour_left.colour == PURPLE:
  332.                         prev_move = 'L'
  333.                         route_string += "L"
  334.                         current_x = current_x - 1
  335.                        
  336.                     if neighbour_right.colour == PURPLE:
  337.                         prev_move = 'R'
  338.                         route_string += "R"
  339.                         current_x = current_x + 1
  340.                     #print(route_string)
  341.                     current_pos = grid[current_x][current_y]
  342.  
  343.                     #while not at the end
  344.                     while current_pos.colour != TURQUOISE:
  345.                         neighbour_up = grid[current_x][current_y - 1]
  346.                         neighbour_down = grid[current_x][current_y + 1]
  347.                         neighbour_left = grid[current_x - 1][current_y]
  348.                         neighbour_right = grid[current_x + 1][current_y]
  349.  
  350.                                                 #move to the next unexplored cell on the shortest path
  351.                         if neighbour_up.colour == PURPLE and prev_move != 'D':
  352.                             prev_move = 'U'
  353.                             route_string += "U"
  354.                             current_y = current_y - 1
  355.                        
  356.                         elif neighbour_left.colour == PURPLE and prev_move != 'R':
  357.                             prev_move = 'L'
  358.                             route_string += "L"
  359.                             current_x = current_x - 1
  360.                            
  361.                         elif neighbour_right.colour == PURPLE and prev_move != 'L':
  362.                             prev_move = 'R'
  363.                             route_string += "R"
  364.                             current_x = current_x + 1
  365.  
  366.                         elif neighbour_down.colour == PURPLE and prev_move != 'U':
  367.                             prev_move = 'D'
  368.                             route_string += "D"
  369.                             current_y = current_y + 1
  370.  
  371.                         else:
  372.                             break
  373.  
  374.                         #print(route_string)
  375.                         current_pos = grid[current_x][current_y]
  376.  
  377.                     #print(route_string)
  378.                    
  379.                     #clean up string & write to text file
  380.                     count = 1
  381.                     compact_route_string = ""
  382.                     for i in range(1, len(route_string) + 1):
  383.                         if i == len(route_string):
  384.                             compact_route_string += route_string[i - 1] + str(count)
  385.                             break
  386.                         elif route_string[i - 1] == route_string[i]:
  387.                             count += 1
  388.                         else:
  389.                             compact_route_string += route_string[i - 1] + str(count)
  390.                             count = 1
  391.  
  392.                     #print(compact_route_string)
  393.  
  394.                     compact_route_string_spaced = ""
  395.                     compact_route_string_spaced = compact_route_string[0] + ","
  396.  
  397.                     for i in range(1, len(compact_route_string)):
  398.                         try:
  399.                             int(compact_route_string[i])
  400.                             compact_route_string_spaced += compact_route_string[i]
  401.                         except:
  402.                             compact_route_string_spaced += "," + compact_route_string[i] + ","
  403.  
  404.                     print(compact_route_string_spaced)
  405.                    
  406.                     extracted_route = open(path2,'a')
  407.                     extracted_route.write(compact_route_string_spaced)
  408.                     extracted_route.close()
  409.  
  410.                     with io.BytesIO(compact_route_string_spaced.encode()) as stream:
  411.                         stream.seek(0)
  412.  
  413.                         # Write a text file
  414.                         DBX.files_upload(stream.read(), "/extracted_route.txt", mode=dropbox.files.WriteMode.overwrite)
  415.                        
  416.  
  417.     pygame.quit()
  418.  
  419. main(WIN, WIDTH, ROWS)
  420.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement