now the vacuum can only go straight and rotate left/right to change direction

This commit is contained in:
Eikthyrnir 2023-04-21 13:11:52 +02:00
parent c95ce82ac4
commit afdcac8b56
5 changed files with 129 additions and 19 deletions

3
.gitignore vendored
View File

@ -2,3 +2,6 @@
.DS_Store .DS_Store
/.vscode /.vscode
__pycache__ __pycache__
#PyCharm
.idea/

78
AI_brain/template_bfs.py Normal file
View File

@ -0,0 +1,78 @@
import queue
from domain.commands.vacuum_move_command import VacuumMoveCommand
from domain.world import World
class State:
def __init__(self, x, y, direction=(1, 0)):
self.x = x
self.y = y
self.direction = direction
def __hash__(self):
return hash((self.x, self.y))
def __eq__(self, other):
return (self.x == other.x and self.y == other.y
and self.direction == other.direction)
class Node:
def __init__(self, state: State):
self.state = state
self.parent = None
self.action = None
def action_sequence(node: Node):
actions = []
while node.parent:
actions.append(node.action)
node = node.parent
actions.reverse()
return actions
class TemplateBFS:
def __init__(self, world: World, start_state: State, goal_state: State):
self.world = world
self.start_state = start_state
self.goal_state = goal_state
self.fringe = queue.Queue()
self.enqueued_states = set()
self.explored = set()
self.actions = []
def search(self):
self.fringe.put(Node(self.start_state))
while self.fringe:
elem = self.fringe.get()
if elem.state == self.goal_state:
self.actions = action_sequence(elem)
return True
self.explored.add(elem.state)
for (action, state) in self.successors(elem.state):
if state in self.explored or state in self.enqueued_states:
continue
next_node = Node(state)
next_node.action = action
next_node.parent = elem
self.fringe.put(next_node)
self.enqueued_states.add(state)
return False
def successors(self, state: State):
new_successors = [
# ("GO", State(state.x + state.direction[0], state.y + state.direction[1], state.direction)),
# rotate right
("RR", State(state.x, state.y, (-state.direction[1], state.direction[0]))),
# rotate left
("RL", State(state.x, state.y, (state.direction[1], -state.direction[0]))),
]
if self.world.accepted_move(state.x + state.direction[0], state.y + state.direction[1]):
new_successors.append(("GO", State(state.x + state.direction[0], state.y + state.direction[1], state.direction)))
return new_successors

View File

@ -5,6 +5,7 @@ from domain.world import World
class Vacuum(Entity): class Vacuum(Entity):
def __init__(self, x: int, y: int): def __init__(self, x: int, y: int):
super().__init__(x, y, "VACUUM") super().__init__(x, y, "VACUUM")
self.direction = (1, 0)
self.battery = 100 self.battery = 100
self.cleaning_detergent = 100 self.cleaning_detergent = 100
self.container_filling = 0 self.container_filling = 0

53
main.py
View File

@ -11,7 +11,8 @@ from domain.entities.vacuum import Vacuum
from domain.entities.docking_station import Doc_Station from domain.entities.docking_station import Doc_Station
from domain.world import World from domain.world import World
from view.renderer import Renderer from view.renderer import Renderer
from AI_brain.movement import StateGraphSearchBFS, State # from AI_brain.movement import StateGraphSearchBFS, State
from AI_brain.template_bfs import TemplateBFS, State
config = configparser.ConfigParser() config = configparser.ConfigParser()
@ -48,7 +49,8 @@ class Main:
start_state = State(self.world.vacuum.x, self.world.vacuum.y) start_state = State(self.world.vacuum.x, self.world.vacuum.y)
end_state = State(self.world.doc_station.x, self.world.doc_station.y) end_state = State(self.world.doc_station.x, self.world.doc_station.y)
SGS_BFS = StateGraphSearchBFS(self.world, start_state, end_state) # SGS_BFS = StateGraphSearchBFS(self.world, start_state, end_state)
SGS_BFS = TemplateBFS(self.world, start_state, end_state)
if not SGS_BFS.search(): if not SGS_BFS.search():
print("No solution") print("No solution")
exit(0) exit(0)
@ -59,26 +61,41 @@ class Main:
self.clock.tick(5) self.clock.tick(5)
if len(SGS_BFS.actions) > 0: if len(SGS_BFS.actions) > 0:
action_direction = SGS_BFS.actions.pop() action_direction = SGS_BFS.actions.pop()
if action_direction == "UP": # self.handle_action1(action_direction)
self.commands.append( self.handle_action2(action_direction)
VacuumMoveCommand(self.world, self.world.vacuum, (0, -1))
)
elif action_direction == "DOWN":
self.commands.append(
VacuumMoveCommand(self.world, self.world.vacuum, (0, 1))
)
elif action_direction == "LEFT":
self.commands.append(
VacuumMoveCommand(self.world, self.world.vacuum, (-1, 0))
)
elif action_direction == "RIGHT":
self.commands.append(
VacuumMoveCommand(self.world, self.world.vacuum, (1, 0))
)
self.update() self.update()
pygame.quit() pygame.quit()
def handle_action1(self, action):
if action == "UP":
self.commands.append(
VacuumMoveCommand(self.world, self.world.vacuum, (0, -1))
)
elif action == "DOWN":
self.commands.append(
VacuumMoveCommand(self.world, self.world.vacuum, (0, 1))
)
elif action == "LEFT":
self.commands.append(
VacuumMoveCommand(self.world, self.world.vacuum, (-1, 0))
)
elif action == "RIGHT":
self.commands.append(
VacuumMoveCommand(self.world, self.world.vacuum, (1, 0))
)
def handle_action2(self, action):
if action == "GO":
self.commands.append(
VacuumMoveCommand(self.world, self.world.vacuum, self.world.vacuum.direction)
)
elif action == "RR":
self.world.vacuum.direction = (-self.world.vacuum.direction[1], self.world.vacuum.direction[0])
elif action == "RL":
self.world.vacuum.direction = (self.world.vacuum.direction[1], -self.world.vacuum.direction[0])
def process_input(self): def process_input(self):
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:

View File

@ -159,6 +159,7 @@ class Renderer:
draw_pos[1] + self.tile_height, draw_pos[1] + self.tile_height,
) )
self.screen.blit(text_surface, text_pos) self.screen.blit(text_surface, text_pos)
sprite = self.create_vacuum_sprite(entity)
if "DOC_STATION" in entity.type: if "DOC_STATION" in entity.type:
draw_pos = ( draw_pos = (
(entity.x - 0.1) * self.tile_width, (entity.x - 0.1) * self.tile_width,
@ -166,6 +167,16 @@ class Renderer:
) )
self.screen.blit(sprite, draw_pos) self.screen.blit(sprite, draw_pos)
def create_vacuum_sprite(self, vacuum):
angles = {
(1, 0): 0,
(-1, 0): 180,
(0, 1): 270,
(0, -1): 90,
}
init_sprite = self.sprites.get(vacuum.type, None)
return pygame.transform.rotate(init_sprite, angles[vacuum.direction])
def draw_sprite(self, x: int, y: int, sprite_name: str): def draw_sprite(self, x: int, y: int, sprite_name: str):
self.screen.blit( self.screen.blit(
self.sprites[sprite_name], (x * self.tile_width, y * self.tile_height) self.sprites[sprite_name], (x * self.tile_width, y * self.tile_height)