diff --git a/.idea/SztIn_gr.234798.iml b/.idea/SztIn_gr.234798.iml
index d0876a7..8388dbc 100644
--- a/.idea/SztIn_gr.234798.iml
+++ b/.idea/SztIn_gr.234798.iml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index dc9ea49..d56657a 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/dijkstra_example_yt.py b/dijkstra_example_yt.py
new file mode 100644
index 0000000..2c57a9d
--- /dev/null
+++ b/dijkstra_example_yt.py
@@ -0,0 +1,94 @@
+import pygame as pg
+from heapq import *
+
+#https://www.youtube.com/watch?v=abHftC1GU6w
+
+
+def get_circle(x, y):
+ return (x * TILE + TILE // 2, y * TILE + TILE // 2), TILE // 4
+
+
+def get_rect(x, y):
+ return x * TILE + 1, y * TILE + 1, TILE - 2, TILE - 2
+
+
+def get_next_nodes(x, y):
+ check_next_node = lambda x, y: True if 0 <= x < cols and 0 <= y < rows else False
+ ways = [-1, 0], [0, -1], [1, 0], [0, 1]
+ return [(grid[y + dy][x + dx], (x + dx, y + dy)) for dx, dy in ways if check_next_node(x + dx, y + dy)]
+
+
+cols, rows = 23, 13
+TILE = 70
+
+pg.init()
+sc = pg.display.set_mode([cols * TILE, rows * TILE])
+clock = pg.time.Clock()
+# grid
+grid = ['22222222222222222222212',
+ '22222292222911112244412',
+ '22444422211112911444412',
+ '24444444212777771444912',
+ '24444444219777771244112',
+ '92444444212777791192144',
+ '22229444212777779111144',
+ '11111112212777772771122',
+ '27722211112777772771244',
+ '27722777712222772221244',
+ '22292777711144429221244',
+ '22922777222144422211944',
+ '22222777229111111119222']
+grid = [[int(char) for char in string ] for string in grid]
+# dict of adjacency lists
+graph = {}
+for y, row in enumerate(grid):
+ for x, col in enumerate(row):
+ graph[(x, y)] = graph.get((x, y), []) + get_next_nodes(x, y)
+
+# BFS settings
+start = (0, 7)
+goal = (22, 7)
+queue = []
+heappush(queue, (0, start))
+cost_visited = {start: 0}
+visited = {start: None}
+
+bg = pg.image.load('images/field_image.png').convert()
+bg = pg.transform.scale(bg, (cols * TILE, rows * TILE))
+
+while True:
+ # fill screen
+ sc.blit(bg, (0, 0))
+ # draw BFS work
+ [pg.draw.rect(sc, pg.Color('forestgreen'), get_rect(x, y), 1) for x, y in visited]
+ [pg.draw.rect(sc, pg.Color('darkslategray'), get_rect(*xy)) for _, xy in queue]
+ pg.draw.circle(sc, pg.Color('purple'), *get_circle(*goal))
+
+ # Dijkstra logic
+ if queue:
+ cur_cost, cur_node = heappop(queue)
+ if cur_node == goal:
+ queue = []
+ continue
+
+ next_nodes = graph[cur_node]
+ for next_node in next_nodes:
+ neigh_cost, neigh_node = next_node
+ new_cost = cost_visited[cur_node] + neigh_cost
+
+ if neigh_node not in cost_visited or new_cost < cost_visited[neigh_node]:
+ heappush(queue, (new_cost, neigh_node))
+ cost_visited[neigh_node] = new_cost
+ visited[neigh_node] = cur_node
+
+ # draw path
+ path_head, path_segment = cur_node, cur_node
+ while path_segment:
+ pg.draw.circle(sc, pg.Color('brown'), *get_circle(*path_segment))
+ path_segment = visited[path_segment]
+ pg.draw.circle(sc, pg.Color('blue'), *get_circle(*start))
+ pg.draw.circle(sc, pg.Color('magenta'), *get_circle(*path_head))
+ # pygame necessary lines
+ [exit() for event in pg.event.get() if event.type == pg.QUIT]
+ pg.display.flip()
+ clock.tick(7)
\ No newline at end of file
diff --git a/field.py b/field.py
index 8effece..e21d38e 100644
--- a/field.py
+++ b/field.py
@@ -1,5 +1,7 @@
import random
-from enum import Enum
+from heapq import *
+from enum import Enum, IntEnum
+from collections import deque
import pygame
@@ -18,43 +20,25 @@ GAS_TANK_CAPACITY = 100
SPAWN_POINT = (0, 0)
-def generate_locations(number, flag=False, rocks=[]):
- locations = []
- if flag:
- for i in range(number):
- x = random.randrange(0, BOARD_SIZE)
- y = random.randrange(0, BOARD_SIZE)
- if (x, y) not in rocks and (x, y, 'Potato') not in locations and (x, y, 'Broccoli') not in locations and (
- x, y, 'Carrot') not in locations and (x, y, 'Onion') not in locations:
- locations.append((x, y, VEGETABLES[random.randrange(0, len(VEGETABLES))]))
- else:
- i -= 1
- return locations
- else:
- for i in range(number):
- x = random.randrange(0, BOARD_SIZE - 1)
- y = random.randrange(0, BOARD_SIZE - 1)
- if (x, y) not in locations and (x, y) != (0, 0):
- locations.append((x, y))
- else:
- i -= 1
- return locations
-
-
def draw_grid():
# Set the size of the grid block
wei = pygame.transform.scale(pygame.image.load("images/wet_earth_tile.jpg"), (BLOCK_SIZE, BLOCK_SIZE))
dei = pygame.transform.scale(pygame.image.load("images/dry_earth_tile.jpg"), (BLOCK_SIZE, BLOCK_SIZE))
for x in range(0, BOARD_SIZE):
for y in range(0, BOARD_SIZE):
- if (x, y) in wet_tiles_coordinates:
- sc.blit(wei, (x * BLOCK_SIZE, y * BLOCK_SIZE))
- else:
- sc.blit(dei, (x * BLOCK_SIZE, y * BLOCK_SIZE))
+ sc.blit(wei, (x * BLOCK_SIZE, y * BLOCK_SIZE))
rect = pygame.Rect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
pygame.draw.rect(sc, WHITE, rect, 1)
+def get_click_mouse_pos():
+ x, y = pygame.mouse.get_pos()
+ grid_x, grid_y = x // BLOCK_SIZE, y // BLOCK_SIZE
+ pygame.draw.rect(sc, BLUE, (grid_x * BLOCK_SIZE, grid_y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 1)
+ click = pygame.mouse.get_pressed()
+ return (grid_x, grid_y) if click[0] else False
+
+
def draw_interface():
global sc
sc = pygame.display.set_mode((WINDOW_DIMENSIONS, WINDOW_DIMENSIONS))
@@ -67,7 +51,7 @@ def draw_interface():
# region Images import
# bg = pygame.image.load("images/field_image.jpg")
- tractor_image= pygame.transform.scale(pygame.image.load("images/tractor_image.png"), (BLOCK_SIZE, BLOCK_SIZE))
+ tractor_image = pygame.transform.scale(pygame.image.load("images/tractor_image.png"), (BLOCK_SIZE, BLOCK_SIZE))
rock_image = pygame.transform.scale(pygame.image.load("images/rock_image.png"), (BLOCK_SIZE, BLOCK_SIZE))
potato_image = pygame.transform.scale(pygame.image.load("images/potato.png"), (BLOCK_SIZE, BLOCK_SIZE))
carrot_image = pygame.transform.scale(pygame.image.load("images/carrot.png"), (BLOCK_SIZE, BLOCK_SIZE))
@@ -78,137 +62,96 @@ def draw_interface():
# endregion
(x, y) = SPAWN_POINT
+ tractor = Tractor(x, y, Direction.RIGHT)
- rocks = generate_locations(ROCKS_NUMBER)
- vegetables = generate_locations(VEGETABLES_NUMBER, flag=True, rocks=rocks)
- water_left = WATER_TANK_CAPACITY
- gas_left = GAS_TANK_CAPACITY
- collected_vegetables = [0, 0, 0, 0]
- global wet_tiles_coordinates
- wet_tiles_coordinates = []
+ grid = Grid(BOARD_SIZE, BOARD_SIZE, BLOCK_SIZE)
fl_running = True
while fl_running:
draw_grid()
- #region events
+ # region events
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
fl_running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
- if x > 0:
- x -= 1
- if (x - 1, y) not in rocks:
- gas_left -= 1
- else:
- print('Rock')
- gas_left -= 5
+ tractor.rot_center(Direction.LEFT)
elif event.key == pygame.K_RIGHT:
- if x < BOARD_SIZE - 1:
- x += 1
- if (x + 1, y) not in rocks:
- gas_left -= 1
- else:
- gas_left -= 5
- print("Rock")
- elif event.key == pygame.K_DOWN:
- if y < BOARD_SIZE - 1:
- y += 1
- if (x, y + 1) not in rocks:
- gas_left -= 1
- else:
- gas_left -= 5
- print("Rock")
+ tractor.rot_center(Direction.RIGHT)
elif event.key == pygame.K_UP:
- if y > 0:
- y -= 1
- if (x, y - 1) not in rocks:
- gas_left -= 1
- else:
- gas_left -= 5
- print("Rock")
- elif event.key == pygame.K_SPACE:
- if water_left >= 1:
- water_left -= 1
- wet_tiles_coordinates.append((x, y))
+ tractor.move(grid=grid)
elif event.key == pygame.K_RETURN:
- for vegetable in vegetables:
- if vegetable[0] == x and vegetable[1] == y:
- if vegetable[2] == 'Potato':
- print("Potato collected")
- collected_vegetables[0] += 1
- elif vegetable[2] == 'Broccoli':
- print("Broccoli collected")
- collected_vegetables[1] += 1
- elif vegetable[2] == 'Carrot':
- print("Carrot collected")
- collected_vegetables[2] += 1
- elif vegetable[2] == 'Onion':
- print("Onion collected")
- collected_vegetables[3] += 1
- vegetables.remove(vegetable)
- break
- if (x, y) == SPAWN_POINT:
- water_left = WATER_TANK_CAPACITY
- gas_left = GAS_TANK_CAPACITY
+ for y, row in enumerate(grid.grid):
+ for x, col in enumerate(row):
+ if col in [item.value for item in vegetables] and (x, y) == (tractor.x, tractor.y):
+ tractor.collected_vegetables[vegetables(col)] += 1
+ grid.remove_object(x, y)
+ break
+ if (tractor.x, tractor.y) == SPAWN_POINT:
+ tractor.water = WATER_TANK_CAPACITY
+ tractor.gas = GAS_TANK_CAPACITY
- #endregion
+ # endregion
- for rock in rocks:
- sc.blit(rock_image, (rock[0] * BLOCK_SIZE, rock[1] * BLOCK_SIZE))
- for vegetable in vegetables:
- if vegetable[2] == 'Potato':
- sc.blit(potato_image, (vegetable[0] * BLOCK_SIZE + 5, vegetable[1] * BLOCK_SIZE + 5))
- elif vegetable[2] == 'Carrot':
- sc.blit(carrot_image, (vegetable[0] * BLOCK_SIZE + 5, vegetable[1] * BLOCK_SIZE + 5))
- elif vegetable[2] == 'Broccoli':
- sc.blit(broccoli_image, (vegetable[0] * BLOCK_SIZE + 5, vegetable[1] * BLOCK_SIZE + 5))
- elif vegetable[2] == 'Onion':
- sc.blit(onion_image, (vegetable[0] * BLOCK_SIZE + 5, vegetable[1] * BLOCK_SIZE + 5))
+ for y, row in enumerate(grid.grid):
+ for x, col in enumerate(row):
+ if grid.grid[x][y] == vegetables.POTATO:
+ sc.blit(potato_image, (x * BLOCK_SIZE + 5, y * BLOCK_SIZE + 5))
+ elif grid.grid[x][y] == vegetables.CARROT:
+ sc.blit(carrot_image, (x * BLOCK_SIZE + 5, y * BLOCK_SIZE + 5))
+ elif grid.grid[x][y] == vegetables.BROCCOLI:
+ sc.blit(broccoli_image, (x * BLOCK_SIZE + 5, y * BLOCK_SIZE + 5))
+ elif grid.grid[x][y] == vegetables.ONION:
+ sc.blit(onion_image, (x * BLOCK_SIZE + 5, y * BLOCK_SIZE + 5))
+ elif grid.grid[x][y] == types.ROCK:
+ sc.blit(rock_image, (x * BLOCK_SIZE, y * BLOCK_SIZE))
sc.blit(gas_station_image, (SPAWN_POINT[0] * BLOCK_SIZE, SPAWN_POINT[1] * BLOCK_SIZE))
# region text
- vegetables_text = font.render('Potato: ' + str(collected_vegetables[0]) + ' Broccoli: ' + str(
- collected_vegetables[1]) + ' Carrot: ' + str(collected_vegetables[2]) + ' Onion: ' + str(
- collected_vegetables[3]), True, WHITE, BLACK)
- vegetables_textRect = vegetables_text.get_rect()
- vegetables_textRect.center = (WINDOW_DIMENSIONS // 2, WINDOW_DIMENSIONS - 30)
- sc.blit(vegetables_text, vegetables_textRect)
+ vegetables_text = font.render(
+ 'Potato: ' + str(tractor.collected_vegetables[vegetables.POTATO]) + ' Broccoli: ' + str(
+ tractor.collected_vegetables[vegetables.BROCCOLI]) + ' Carrot: ' + str(
+ tractor.collected_vegetables[vegetables.CARROT]) + ' Onion: ' + str(
+ tractor.collected_vegetables[vegetables.ONION]), True, WHITE, BLACK)
+ vegetables_textrect = vegetables_text.get_rect()
+ vegetables_textrect.center = (WINDOW_DIMENSIONS // 2, WINDOW_DIMENSIONS - 30)
+ sc.blit(vegetables_text, vegetables_textrect)
- water_text = font.render('Waterd tank: ' + str(water_left), True, WHITE, BLACK)
- water_textRect = water_text.get_rect()
- water_textRect.center = (WINDOW_DIMENSIONS // 4, 20)
- sc.blit(water_text, water_textRect)
-
- gas_text = font.render('Gas tank: ' + str(gas_left), True, WHITE, BLACK)
- gas_textRect = gas_text.get_rect()
- gas_textRect.center = (WINDOW_DIMENSIONS // 4 * 3, 20)
- sc.blit(gas_text, gas_textRect)
+ gas_text = font.render('Gas tank: ' + str(tractor.gas), True, WHITE, BLACK)
+ gas_textrect = gas_text.get_rect()
+ gas_textrect.center = (WINDOW_DIMENSIONS // 4 * 3, 20)
+ sc.blit(gas_text, gas_textrect)
# endregion
- sc.blit(tractor_image, (x * BLOCK_SIZE + 5, y * BLOCK_SIZE + 5))
+ sc.blit(tractor.image, (tractor.x * BLOCK_SIZE + 5, tractor.y * BLOCK_SIZE + 5))
pygame.display.update()
clock.tick(FPS)
-class types(Enum):
- EMPTY = 0
- ROCK = 1
- TRACTOR = 2
+class Direction(IntEnum):
+ UP = 0
+ RIGHT = 1
+ DOWN = 2
+ LEFT = 3
+
+
+class vegetables(Enum):
POTATO = 3
BROCCOLI = 4
CARROT = 5
ONION = 6
-class objectOnField:
- def __init__(self, x, y, type):
- self.x = x
- self.y = y
- self.type = type
+class types(Enum):
+ EMPTY = 0
+ ROCK = 1
+ POTATO = 3
+ BROCCOLI = 4
+ CARROT = 5
+ ONION = 6
class Grid:
@@ -216,9 +159,110 @@ class Grid:
self.width = width
self.height = height
self.block_size = block_size
- self.grid = []
- self.vegetables = []
- self.rocks = []
- self.tractor = None
- self.wet_tiles = []
- self.generate_grid()
+ self.grid = [[types.EMPTY for col in range(BOARD_SIZE)] for row in range(BOARD_SIZE)]
+ self.graph = {}
+ self.initialize_grid()
+
+ def add_object(self, x, y, type_of_object: types):
+ if self.grid[x][y] == types.EMPTY:
+ self.grid[x][y] = type_of_object
+ return True
+ else:
+ return False
+
+ def remove_object(self, x, y):
+ if self.grid[x][y] != types.EMPTY:
+ self.grid[x][y] = types.EMPTY
+ return True
+ else:
+ return False
+
+ def initialize_grid(self):
+ for i in range(VEGETABLES_NUMBER):
+ x, y = random.randrange(0, BOARD_SIZE), random.randrange(0, BOARD_SIZE)
+ if self.grid[x][y] == types.EMPTY and (x, y) != (0, 0):
+ self.add_object(x, y, random.choice(list(vegetables)))
+ else:
+ i -= 1
+ for i in range(ROCKS_NUMBER):
+ x, y = random.randrange(0, BOARD_SIZE - 1), random.randrange(0, BOARD_SIZE - 1)
+ if self.grid[x][y] == types.EMPTY and (x, y) != (0, 0):
+ self.add_object(x, y, types.ROCK)
+ else:
+ i -= 1
+
+ def get_next_nodes(self, x, y):
+ check_next_node = lambda x, y: True if 0 <= x < BOARD_SIZE and 0 <= y < BOARD_SIZE and (
+ self.grid[x][y] != types.ROCK) else False
+ ways = [-1, 0], [1, 0], [0, -1], [0, 1]
+ return [(x + dx, y + dy) for dx, dy in ways if check_next_node(x + dx, y + dy)]
+
+
+class Graph:
+ def __init__(self, grid: Grid):
+ self.graph = {}
+ self.initialize_graph(grid)
+
+ def initialize_graph(self, grid: Grid):
+ for y, row in enumerate(grid.grid):
+ for x, col in enumerate(row):
+ if col != types.ROCK:
+ self.graph[(x, y)] = self.graph.get((x, y), []) + grid.get_next_nodes(x, y)
+
+ def dijkstra(self, start, goal):
+ #not finished yet https://www.youtube.com/watch?v=abHftC1GU6w
+ queue = []
+ heappush(queue, (0, start))
+ cost_visited = {start: 0}
+ visited = {start: None}
+
+ while queue:
+ cur_cost, cur_node = heappop(queue)
+ if cur_node == goal:
+ break
+
+ next_nodes = self.graph[cur_node]
+ for next_node in next_nodes:
+ neigh_cost, neigh_node = next_node
+ new_cost = cost_visited[cur_node] + neigh_cost
+ if neigh_node not in cost_visited or new_cost < cost_visited[neigh_node]:
+ heappush(queue, (new_cost, neigh_node))
+ cost_visited[neigh_node] = new_cost
+ visited[neigh_node] = cur_node
+ return visited
+
+class Tractor:
+ def __init__(self, x, y, direction: Direction):
+ self.x = x
+ self.y = y
+ self.direction = direction
+ self.gas = GAS_TANK_CAPACITY
+ self.water = WATER_TANK_CAPACITY
+ self.collected_vegetables = {vegetables.POTATO: 0, vegetables.BROCCOLI: 0, vegetables.CARROT: 0,
+ vegetables.ONION: 0}
+ self.image = pygame.transform.scale(pygame.image.load("images/tractor_image.png"), (BLOCK_SIZE, BLOCK_SIZE))
+
+ def rot_center(self, direc: Direction):
+ self.image = pygame.transform.rotate(self.image, - int(direc) * 90)
+ self.direction = ((int(self.direction) + int(direc)) % 4)
+ return
+
+ def move(self, grid: Grid):
+ if self.direction == Direction.UP:
+ if self.y > 0:
+ self.y -= 1
+ elif self.direction == Direction.RIGHT:
+ if self.x < BOARD_SIZE - 1:
+ self.x += 1
+ elif self.direction == Direction.DOWN:
+ if self.y < BOARD_SIZE - 1:
+ self.y += 1
+ elif self.direction == Direction.LEFT:
+ if self.x > 0:
+ self.x -= 1
+
+ if grid.grid[self.x][self.y] == types.ROCK:
+ self.gas -= 5
+ else:
+ self.gas -= 1
+ return