Merge pull request 'snake_move' (#16) from snake_move into BFS

Reviewed-on: #16
This commit is contained in:
s481834 2024-04-24 17:41:46 +02:00
commit da6b3ef067
11 changed files with 505 additions and 104 deletions

71
App.py

File diff suppressed because one or more lines are too long

262
BFS.py Normal file
View File

@ -0,0 +1,262 @@
import random
import pygame
import Node
from displayControler import NUM_X, NUM_Y
def goalTest1(hIndex):
for i in list(hIndex.values()):
if i == 0:
return False
return True
def succ1(state):
resp = []
hIndex = state["hydradeIndex"].copy()
if state["direction"] == "N":
if state["y"] > 0:
if hIndex[state["x"], state["y"]-1] == 0:
hIndex[state["x"], state["y"] - 1] = 1
resp.append(["forward", {'x': state["x"], 'y': state["y"]-1, 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "E", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "W", 'hydradeIndex': state["hydradeIndex"].copy()}])
elif state["direction"] == "S":
if state["y"] < NUM_Y-1:
if hIndex[state["x"], state["y"]+1] == 0:
hIndex[state["x"], state["y"] + 1] = 1
resp.append(["forward", {'x': state["x"], 'y': state["y"]+1, 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "W", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "E", 'hydradeIndex': state["hydradeIndex"].copy()}])
elif state["direction"] == "E":
if state["x"] < NUM_X-1:
if hIndex[state["x"]+1, state["y"]] == 0:
hIndex[state["x"] + 1, state["y"]] = 1
resp.append(["forward", {'x': state["x"]+1, 'y': state["y"], 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "S", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "N", 'hydradeIndex': state["hydradeIndex"].copy()}])
else: #state["zwrot"] == "W"
if state["x"] > 0:
if hIndex[state["x"]-1, state["y"]] == 0:
hIndex[state["x"] - 1, state["y"]] = 1
resp.append(["forward", {'x': state["x"]-1, 'y': state["y"], 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "N", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "S", 'hydradeIndex': state["hydradeIndex"].copy()}])
return resp
def check1(tab, state):
for i in tab:
if i.state == state:
return False
return True
def BFS1(istate):
fringe = []
explored = []
x = Node.Node(istate)
fringe.append(x)
while True:
if fringe == []:
return False
elem = fringe.pop(0)
if goalTest1(elem.state["hydradeIndex"]):
x = elem
tab = []
while x.parent != None:
tab.append([x.parent, x.action])
x = x.parent
return tab
explored.append(elem)
for resp in succ1(elem.state):
if check1(fringe, resp[1]) and check1(explored, resp[1]):
x = Node.Node(resp[1])
x.parent = elem
x.action = resp[0]
fringe.append(x)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
def goalTest2(state, goalTreassure):
if state["x"] == goalTreassure[0] and state["y"] == goalTreassure[1]:
return True
return False
def succ2(state):
resp = []
if state["direction"] == "N":
if state["y"] > 0:
resp.append(["forward", {'x': state["x"], 'y': state["y"]-1, 'direction': state["direction"]}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "E"}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "W"}])
elif state["direction"] == "S":
if state["y"] < NUM_Y:
resp.append(["forward", {'x': state["x"], 'y': state["y"]+1, 'direction': state["direction"]}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "W"}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "E"}])
elif state["direction"] == "E":
if state["x"] < NUM_X:
resp.append(["forward", {'x': state["x"]+1, 'y': state["y"], 'direction': state["direction"]}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "S"}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "N"}])
else: #state["zwrot"] == "W"
if state["x"] > 0:
resp.append(["forward", {'x': state["x"]-1, 'y': state["y"], 'direction': state["direction"]}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "N"}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "S"}])
return resp
def check2(tab, state):
for i in tab:
if i.state == state:
return False
return True
def BFS2(istate):
goalTreassuere = (random.randint(0,NUM_X-1), random.randint(0,NUM_Y-1))
print(goalTreassuere)
fringe = []
explored = []
x = Node.Node(istate)
fringe.append(x)
while True:
if fringe == []:
return False
elem = fringe.pop(0)
if goalTest2(elem.state, goalTreassuere):
x = elem
tab = []
while x.parent != None:
tab.append([x.parent, x.action])
x = x.parent
return tab
explored.append(elem)
for resp in succ2(elem.state):
if check2(fringe, resp[1]) and check2(explored, resp[1]):
x = Node.Node(resp[1])
x.parent = elem
x.action = resp[0]
fringe.append(x)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
"""
def goalTest(hIndex):
for i in list(hIndex.values()):
if i == 0:
return False
return True
def succ(state):
resp = []
hIndex = state["hydradeIndex"].copy()
if state["direction"] == "N":
if state["y"] > 0:
if hIndex[state["x"], state["y"]-1] == 0:
hIndex[state["x"], state["y"] - 1] = 1
resp.append(["forward", {'x': state["x"], 'y': state["y"]-1, 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "E", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "W", 'hydradeIndex': state["hydradeIndex"].copy()}])
elif state["direction"] == "S":
if state["y"] < dCon.NUM_Y-1:
if hIndex[state["x"], state["y"]+1] == 0:
hIndex[state["x"], state["y"] + 1] = 1
resp.append(["forward", {'x': state["x"], 'y': state["y"]+1, 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "W", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "E", 'hydradeIndex': state["hydradeIndex"].copy()}])
elif state["direction"] == "E":
if state["x"] < dCon.NUM_X-1:
if hIndex[state["x"]+1, state["y"]] == 0:
hIndex[state["x"] + 1, state["y"]] = 1
resp.append(["forward", {'x': state["x"]+1, 'y': state["y"], 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "S", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "N", 'hydradeIndex': state["hydradeIndex"].copy()}])
else: #state["direction"] == "W"
if state["x"] > 0:
if hIndex[state["x"]-1, state["y"]] == 0:
hIndex[state["x"] - 1, state["y"]] = 1
resp.append(["forward", {'x': state["x"]-1, 'y': state["y"], 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "N", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "S", 'hydradeIndex': state["hydradeIndex"].copy()}])
return resp
def check(tab, state):
for i in tab:
if i.state == state:
return False
return True
def BFS(istate):
fringe = []
explored = []
x = Node.Node(istate)
fringe.append(x)
while True:
if fringe == []:
return False
elem = fringe.pop(0)
if goalTest(elem.state["hydradeIndex"]):
x = elem
tab = []
while x.parent != None:
tab.append(x.action)
x = x.parent
return tab
explored.append(elem)
for resp in succ(elem.state):
if check(fringe, resp[1]) and check(explored, resp[1]):
x = Node.Node(resp[1])
x.parent = elem
x.action = resp[0]
fringe.append(x)
"""

View File

@ -6,6 +6,7 @@ class Image:
def __init__(self):
self.plants_image_dict={}
self.tractor_image=None
self.garage_image=None
def load_images(self):
files_plants={0:"borowka",
1:"kukurydza",
@ -19,6 +20,8 @@ class Image:
self.plants_image_dict[files_plants[index]]=plant_image
tractor_image=pygame.image.load("images/traktor.png")
tractor_image=pygame.transform.scale(tractor_image,(dCon.CUBE_SIZE,dCon.CUBE_SIZE))
garage=pygame.image.load("images/garage.png")
self.garage_image=pygame.transform.scale(garage,(dCon.CUBE_SIZE,dCon.CUBE_SIZE))
def return_random_plant(self):
x=random.randint(0,5)
keys=list(self.plants_image_dict.keys())
@ -26,4 +29,7 @@ class Image:
return (plant,self.plants_image_dict[plant])
def return_plant(self,plant_name):
return (plant_name,self.plants_image_dict[plant_name])
return (plant_name,self.plants_image_dict[plant_name])
def return_garage(self):
return self.garage_image

14
Pole.py
View File

@ -33,13 +33,18 @@ class Pole:
slot_dict=self.get_slot_dict()
for coordinates in slot_dict:
slot_dict[coordinates].draw()
garage=self.slot_dict[(0,0)]
garage.set_garage_image()
def randomize_colors(self):
pygame.display.update()
time.sleep(3)
self.ui.render_text("Randomizing Crops")
for coordinates in self.slot_dict:
self.slot_dict[coordinates].set_random_plant()
if(coordinates==(0,0)):
continue
else:
self.slot_dict[coordinates].set_random_plant()
def change_color_of_slot(self,coordinates,color): #Coordinates must be tuple (x,y) (left top slot has cord (0,0) ), color has to be from defined in Colors.py or custom in RGB value (R,G,B)
self.get_slot_from_cord(coordinates).color_change(color)
@ -55,5 +60,8 @@ class Pole:
def check_collision(self,mouse_x,mouse_y):
mouse_x=math.floor(mouse_x/dCon.CUBE_SIZE)
mouse_y=math.floor(mouse_y/dCon.CUBE_SIZE)
collided=self.get_slot_from_cord((mouse_x,mouse_y))
return collided.print_status()
if(mouse_x<dCon.NUM_X):
if(mouse_y<dCon.NUM_Y):
collided=self.get_slot_from_cord((mouse_x,mouse_y))
return collided.print_status()
return ""

View File

@ -78,5 +78,11 @@ class Roslina:
self.stan.checkStan()
return
def return_stan(self):
return self.stan
def get_hydrate_stats(self):
return self.stan.return_hydrate()
def report_status(self):
return f"Nazwa rosliny: {self.nazwa} "+self.stan.report_all()

25
Slot.py
View File

@ -15,6 +15,7 @@ class Slot:
self.screen=screen
self.field=pygame.Rect(self.x_axis*dCon.CUBE_SIZE,self.y_axis*dCon.CUBE_SIZE,dCon.CUBE_SIZE,dCon.CUBE_SIZE)
self.image_loader=image_loader
self.garage_image=None
def draw(self):
pygame.draw.rect(self.screen,Colors.BROWN,self.field,0) #Draw field
@ -39,9 +40,31 @@ class Slot:
self.screen.blit(self.plant_image, (self.x_axis * dCon.CUBE_SIZE, self.y_axis * dCon.CUBE_SIZE))
pygame.draw.rect(self.screen, Colors.BLACK, self.field, BORDER_THICKNESS)
def set_garage_image(self):
self.plant_image=self.image_loader.return_garage()
self.screen.blit(self.plant_image, (self.x_axis * dCon.CUBE_SIZE, self.y_axis * dCon.CUBE_SIZE))
pygame.draw.rect(self.screen, Colors.BLACK, self.field, BORDER_THICKNESS)
def random_plant(self): #Probably will not be used later only for demo purpouse
return self.image_loader.return_random_plant()
def return_plant(self):
return self.plant
def get_hydrate_stats(self):
return self.plant.get_hydrate_stats()
def print_status(self):
return f"wspolrzedne: (X:{self.x_axis} Y:{self.y_axis}) "+self.plant.report_status()
return f"wspolrzedne: (X:{self.x_axis} Y:{self.y_axis}) "+self.plant.report_status()
def irrigatePlant(self):
self.plant.stan.nawodnienie = 100
def setHydrate(self,index):
if(index==0):
self.plant.stan.nawodnienie=random.randint(0,60)
elif(index==1):
self.plant.stan.nawodnienie=random.randint(61,100)
elif(index==-1):
pass

View File

@ -44,5 +44,8 @@ class Stan:
self.akcja = None
return
def return_hydrate(self):
return self.nawodnienie
def report_all(self):
return f"Nawodnienie: {self.nawodnienie} Zyznosc: {self.zyznosc} Wzrost: {self.wzrost} Choroba: {self.choroba}"

View File

@ -6,85 +6,11 @@ import Slot
import Osprzet
import Node
def goalTest(hIndex):
for i in list(hIndex.values()):
if i == 0:
return False
return True
def succ(state):
resp = []
hIndex = state["hydradeIndex"].copy()
if state["direction"] == "N":
if state["y"] > 0:
if hIndex[state["x"], state["y"]-1] == 0:
hIndex[state["x"], state["y"] - 1] = 1
resp.append(["forward", {'x': state["x"], 'y': state["y"]-1, 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "E", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "W", 'hydradeIndex': state["hydradeIndex"].copy()}])
elif state["direction"] == "S":
if state["y"] < dCon.NUM_Y-1:
if hIndex[state["x"], state["y"]+1] == 0:
hIndex[state["x"], state["y"] + 1] = 1
resp.append(["forward", {'x': state["x"], 'y': state["y"]+1, 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "W", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "E", 'hydradeIndex': state["hydradeIndex"].copy()}])
elif state["direction"] == "E":
if state["x"] < dCon.NUM_X-1:
if hIndex[state["x"]+1, state["y"]] == 0:
hIndex[state["x"] + 1, state["y"]] = 1
resp.append(["forward", {'x': state["x"]+1, 'y': state["y"], 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "S", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "N", 'hydradeIndex': state["hydradeIndex"].copy()}])
else: #state["direction"] == "W"
if state["x"] > 0:
if hIndex[state["x"]-1, state["y"]] == 0:
hIndex[state["x"] - 1, state["y"]] = 1
resp.append(["forward", {'x': state["x"]-1, 'y': state["y"], 'direction': state["direction"], 'hydradeIndex': hIndex}])
resp.append(["right", {'x': state["x"], 'y': state["y"], 'direction': "N", 'hydradeIndex': state["hydradeIndex"].copy()}])
resp.append(["left", {'x': state["x"], 'y': state["y"], 'direction': "S", 'hydradeIndex': state["hydradeIndex"].copy()}])
return resp
def check(tab, state):
for i in tab:
if i.state == state:
return False
return True
def BFS(istate):
fringe = []
explored = []
x = Node.Node(istate)
fringe.append(x)
while True:
if fringe == []:
return False
elem = fringe.pop(0)
if goalTest(elem.state["hydradeIndex"]):
return elem #TODO ciąg akcji zbudowany z wykorzystaniem pól parent i action
explored.append(elem)
for resp in succ(elem.state):
if check(fringe, resp[1]) and check(explored, resp[1]):
x = Node.Node(resp[1])
x.parent = elem
x.action = resp[0]
fringe.append(x)
tab = [-1, 0, 0, 0, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 0, 1, 0, 1, 1,
0, 1, 0, 1, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
class Tractor:
@ -92,7 +18,7 @@ class Tractor:
DIRECTION_SOUTH = 'S'
DIRECTION_WEST = 'W'
DIRECTION_EAST = 'E'
def __init__(self,slot,screen, osprzet):
def __init__(self,slot,screen, osprzet,clock,bfs2_flag):
self.tractor_images = {
Tractor.DIRECTION_NORTH: pygame.transform.scale(pygame.image.load('images/traktorN.png'),
(dCon.CUBE_SIZE, dCon.CUBE_SIZE)),
@ -108,6 +34,9 @@ class Tractor:
self.screen=screen
self.slot=slot
self.osprzet = osprzet
self.clock=clock
self.slot_hydrate_dict={}
self.bfs2_flag=bfs2_flag
def draw_tractor(self):
@ -154,20 +83,85 @@ class Tractor:
self.current_tractor_image = self.tractor_images[self.direction]
# sprawdzenie czy następny slot jest dobry
self.do_move_if_valid(pole,next_slot_coordinates)
def do_move_if_valid(self,pole, next_slot_coordinates):
if next_slot_coordinates and pole.is_valid_move(next_slot_coordinates):
next_slot = pole.get_slot_from_cord(next_slot_coordinates)
self.slot.redraw_image()
self.slot = next_slot
self.draw_tractor()
return True
else:
return False
def random_move(self, pole):
self.clock.tick(2)
# losowanie skrętu
turn_direction = random.choice([self.turn_left, self.turn_right])
turn_direction()
time.sleep(0.5)
self.clock.tick(5)
# wykonanie ruchu do przodu z uwzględnieniem aktualnej orientacji
self.move_forward(pole)
def reset_pos(self,pole):
self.do_move_if_valid(pole,(0,0))
def initial_move(self,pole):
if (self.bfs2_flag==True):
index=0
for y in range (0,dCon.NUM_Y):
if(y%2==0):
for x in range(0,dCon.NUM_X):
if(pole.is_valid_move((x,y))):
pole.get_slot_from_cord((x,y)).setHydrate(tab[index])
self.snake_move(pole,x,y)
index=index+1
else:
for x in range(dCon.NUM_X,-1,-1):
if(pole.is_valid_move((x,y))):
pole.get_slot_from_cord((x,y)).setHydrate(tab[index])
self.snake_move(pole,x,y)
index=index+1
else:
for y in range (0,dCon.NUM_Y):
if(y%2==0):
for x in range(0,dCon.NUM_X):
self.snake_move(pole,x,y)
else:
for x in range(dCon.NUM_X,-1,-1):
self.snake_move(pole,x,y)
def snake_move(self,pole,x,y):
next_slot_coordinates=(x,y)
if(self.do_move_if_valid(pole,next_slot_coordinates)):
if x == 0 and y == 0:
hydrateIndex = -1
elif pole.get_slot_from_cord((x,y)).get_hydrate_stats() < 60:
hydrateIndex = 0
else:
hydrateIndex = 1
self.slot_hydrate_dict[(x,y)]= hydrateIndex #Budowanie slownika slotow z poziomem nawodnienia dla traktorka
self.clock.tick(10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
def move_by_root(self, root, pole, actions = None):
for move in root:
self.slot.redraw_image()
if move[1] == 'forward':
self.move_forward(pole)
if move[1] == 'right':
self.turn_right()
if move[1] == 'left':
self.turn_left()
for a in actions:
a()
self.clock.tick(3)
#to tak zrobiłam już na później, może się przyda
def change_osprzet(self, new_osprzet):
@ -183,4 +177,9 @@ class Tractor:
print("- Typ:", akcja.typ)
else:
print("Brak akcji przypisanych do tego sprzętu.")
def irrigateSlot(self):
try:
self.slot.irrigatePlant()
except:
pass

31
Ui.py
View File

@ -7,10 +7,35 @@ class Ui:
def __init__(self,screen):
self.screen=screen
self.font='freesansbold.ttf' #Feel free to change it :D
self.font_size=int(32)
if(dCon.NUM_Y<7):
self.font_size=int(15)
self.line=20
self.first_line=20
if(dCon.NUM_Y>=7):
self.font_size=int(30)
self.line=30
self.first_line=30
def render_text(self,string_to_print):
font=pygame.font.Font(self.font,self.font_size)
text=font.render(string_to_print,True,Colors.BLACK,Colors.WHITE)
textRect=text.get_rect()
textRect.center=(dCon.getScreenWidth() // 2,dCon.getScreenHeihgt() // 2)
self.screen.blit(text,textRect)
textRect.center=(dCon.getGameWidth() // 2,dCon.getScreenHeihgt() // 2)
self.screen.blit(text,textRect)
def render_text_to_console(self,string_to_print):
font=pygame.font.Font(self.font,self.font_size)
self.break_string_to_console(string_to_print)
for string in self.to_print:
text=font.render(string,True,Colors.BLACK,Colors.WHITE)
textRect=text.get_rect()
textRect.center=(dCon.getGameWidth()+350/2,self.line)
textRect.scale_by(x=350,y=100)
self.screen.blit(text,textRect)
self.line=self.line+self.first_line
def clear_console(self):
self.line=self.first_line
pygame.draw.rect(self.screen,(0,0,0) , pygame.Rect(dCon.returnConsoleCoordinate(), 0, dCon.getConsoleWidth(), dCon.getScreenHeihgt()), 0)
def break_string_to_console(self,string_to_print):
self.to_print=string_to_print.split(" ")

View File

@ -1,6 +1,6 @@
CUBE_SIZE = 64
NUM_X = 20
NUM_Y = 12
NUM_X = 6
NUM_Y = 3
#returns true if tractor can move to specified slot
def isValidMove(x, y):
@ -10,8 +10,28 @@ def isValidMove(x, y):
return False
return True
def getScreenWidth():
def getGameWidth():
return NUM_X * CUBE_SIZE
def returnConsoleCoordinate():
return NUM_X * CUBE_SIZE
def getScreenHeihgt():
return NUM_Y * CUBE_SIZE
return NUM_Y * CUBE_SIZE
def getScreenWidth(show_console):
screen_width=getGameWidth()
if(show_console):
screen_width=screen_width+350
return screen_width
def getConsoleWidth():
return 350
def getConsoleWidthCenter():
return getScreenWidth()+getConsoleWidth()/2

BIN
images/garage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB