Dodanie obszaru będącego chłodnią, zmiana atrybutów regałów i paczek, mają teraz odpowiednio określoną pojemność(losowaną z zakresu), oraz rozmiar.

This commit is contained in:
andrzej 2020-05-03 18:01:23 +02:00
parent e54769abdd
commit 2cee412170
4 changed files with 80 additions and 29 deletions

View File

@ -1,7 +1,7 @@
from warehouse import Coordinates, Tile, Pack from warehouse import Coordinates, Tile, Pack
from queue import PriorityQueue from queue import PriorityQueue
from math import sqrt from math import sqrt
from attributes import TURN_LEFT_DIRECTIONS, TURN_RIGHT_DIRECTIONS, PackStatus, PackSize from attributes import TURN_LEFT_DIRECTIONS, TURN_RIGHT_DIRECTIONS, PackStatus
import pygame import pygame
import sys import sys
@ -89,7 +89,16 @@ class Agent:
def heuristic(self, start: Node, goal: Node): def heuristic(self, start: Node, goal: Node):
diff_x = pow(goal.x - start.x, 2) diff_x = pow(goal.x - start.x, 2)
diff_y = pow(goal.y - start.y, 2) diff_y = pow(goal.y - start.y, 2)
return round(sqrt(diff_x + diff_y), 3) additional_cost = 0
# if diff_x < diff_y:
# column = self.warehouse.tiles[start.x]
# tiles = column[goal.y:start.y] if goal.y < start.y else column[start.y:goal.y]
# additional_cost += len([t for t in tiles if not t.category.passable])
# elif diff_x > diff_y:
# row = [col[start.x] for col in self.warehouse.tiles]
# tiles = row[goal.x:start.x] if goal.x < start.x else row[start.x:goal.x]
# additional_cost += len([t for t in tiles if not t.category.passable])
return round(sqrt(diff_x + diff_y), 3) + float(10*additional_cost)
def check_if_open(self, node: Node): def check_if_open(self, node: Node):
return (node.x, node.y) in [(n.x, n.y) for (_,n) in self.open.queue] return (node.x, node.y) in [(n.x, n.y) for (_,n) in self.open.queue]
@ -183,7 +192,6 @@ class Agent:
def find_nearest_rack_for(self, package, expand_box=0): def find_nearest_rack_for(self, package, expand_box=0):
weight = package.size weight = package.size
accepted_weights = [weight, PackSize.ALL]
start_node = Node(self.x, self.y) start_node = Node(self.x, self.y)
quarter_x = int(self.warehouse.width/4) + expand_box quarter_x = int(self.warehouse.width/4) + expand_box
quarter_y = int(self.warehouse.height/4) + expand_box quarter_y = int(self.warehouse.height/4) + expand_box
@ -192,7 +200,7 @@ class Agent:
start_quarter_y = self.y - quarter_y if self.y - quarter_y > 0 else 0 start_quarter_y = self.y - quarter_y if self.y - quarter_y > 0 else 0
end_quarter_y = self.y + quarter_y if self.y + quarter_y < self.warehouse.height else self.warehouse.height - 1 end_quarter_y = self.y + quarter_y if self.y + quarter_y < self.warehouse.height else self.warehouse.height - 1
quarter = [row[start_quarter_y:end_quarter_y] for row in self.warehouse.tiles[start_quarter_x:end_quarter_x]] quarter = [row[start_quarter_y:end_quarter_y] for row in self.warehouse.tiles[start_quarter_x:end_quarter_x]]
quarter_racks = [[t for t in row if t.category.name == "Rack" and not t.occupied and t.category.pack_size in accepted_weights] for row in quarter] quarter_racks = [[t for t in row if t.category.name in self.warehouse.storage_types and t.capacity >= weight] for row in quarter]
quarter_racks = [t for row in quarter_racks for t in row] quarter_racks = [t for row in quarter_racks for t in row]
racks_costs = [] racks_costs = []
for rack in quarter_racks: for rack in quarter_racks:
@ -208,7 +216,9 @@ class Agent:
def pick_up_package(self, pack): def pick_up_package(self, pack):
self.warehouse.packages.remove(pack) self.warehouse.packages.remove(pack)
self.is_loaded = True self.is_loaded = True
self.warehouse.tiles[pack.lays_on_field.x_position][pack.lays_on_field.y_position].occupied = False if pack.lays_on_field.category.name in ['Rack', 'Fridge']:
pack.lays_on_field.capacity += pack.size
self.dest.package = None self.dest.package = None
pack.lays_on_field = None pack.lays_on_field = None
self.transported_package = pack self.transported_package = pack
@ -219,6 +229,6 @@ class Agent:
self.transported_package = None self.transported_package = None
self.is_loaded = False self.is_loaded = False
pack.lays_on_field = tile pack.lays_on_field = tile
self.warehouse.tiles[rack.x][rack.y].occupied = True pack.lays_on_field.capacity -= pack.size
pack.status = PackStatus.STORED pack.status = PackStatus.STORED
self.warehouse.packages.append(pack) self.warehouse.packages.append(pack)

View File

@ -1,11 +1,5 @@
from enum import Enum from enum import Enum
class PackSize(Enum):
ALL = 0
SMALL = 1
MEDIUM = 2
LARGE = 3
HUGE = 4
class PackStatus(Enum): class PackStatus(Enum):
LOOSE = 0 LOOSE = 0
@ -25,7 +19,8 @@ COLORS = {
'yellow': (235, 235, 0), 'yellow': (235, 235, 0),
'lightgreen': (70, 238, 70), 'lightgreen': (70, 238, 70),
'red': (255, 0, 0), 'red': (255, 0, 0),
'lightblue': (135, 206, 250), 'lightblue': (120, 180, 230),
'iceblue': (186,242,239),
'orange': (255, 165, 0) 'orange': (255, 165, 0)
} }

19
main.py
View File

@ -3,14 +3,16 @@ import warehouse
import agent import agent
import random import random
import sys import sys
from attributes import PackSize, PackStatus, COLORS, DIRECTION_ANGLES from attributes import PackStatus, COLORS, DIRECTION_ANGLES
WINDOW_SIZE = (640, 640) WINDOW_SIZE = (640, 640)
COLOR_OF_FIELD = { COLOR_OF_FIELD = {
'Floor': 'gray', 'Floor': 'gray',
'Rack': 'white', 'Rack': 'white',
'Pack': 'yellow', 'Pack': 'yellow',
'path': 'orange' 'path': 'orange',
'FridgeFloor': 'lightblue',
'Fridge': 'iceblue'
} }
TILE_WIDTH = 32 TILE_WIDTH = 32
TILE_HEIGHT = 32 TILE_HEIGHT = 32
@ -18,9 +20,12 @@ CIRCLE_CENTER_X, CIRCLE_CENTER_Y = int(TILE_WIDTH/2), int(TILE_HEIGHT/2)
class MainGameFrame: class MainGameFrame:
def __init__(self): def __init__(self):
pygame.font.init()
self.display = pygame.display.set_mode(WINDOW_SIZE) self.display = pygame.display.set_mode(WINDOW_SIZE)
pygame.display.set_caption("Smart ForkLift")
agent_radius = int(TILE_WIDTH/2) agent_radius = int(TILE_WIDTH/2)
self.agent_tex = pygame.image.load('forklift.png') self.agent_tex = pygame.image.load('forklift.png')
self.font = pygame.font.Font('freesansbold.ttf', 16)
self.warehouse_map = warehouse.Warehouse(20, 20, 150, 40) self.warehouse_map = warehouse.Warehouse(20, 20, 150, 40)
starting_x, starting_y = self.set_starting_agent_position() starting_x, starting_y = self.set_starting_agent_position()
self.agent = agent.Agent(starting_x, starting_y, self.warehouse_map, agent_radius) self.agent = agent.Agent(starting_x, starting_y, self.warehouse_map, agent_radius)
@ -35,6 +40,7 @@ class MainGameFrame:
self.draw_floor() self.draw_floor()
self.draw_packages() self.draw_packages()
self.draw_agent() self.draw_agent()
self.draw_nums()
self.agent.move() self.agent.move()
pygame.display.update() pygame.display.update()
self.clock.tick(8) self.clock.tick(8)
@ -52,8 +58,6 @@ class MainGameFrame:
def draw_field(self, x, y): def draw_field(self, x, y):
current_tile = self.warehouse_map.tiles[x][y] current_tile = self.warehouse_map.tiles[x][y]
# if not isinstance(current_tile, warehouse.Tile):
# current_tile = current_tile.lays_on_field if isinstance(current_tile, warehouse.Pack) else None
color = COLOR_OF_FIELD.get(current_tile.category.name, 'white') color = COLOR_OF_FIELD.get(current_tile.category.name, 'white')
color = COLORS[color] color = COLORS[color]
if (current_tile.x_position,current_tile.y_position) in [(a.x, a.y) for a in self.agent.path]: if (current_tile.x_position,current_tile.y_position) in [(a.x, a.y) for a in self.agent.path]:
@ -78,6 +82,13 @@ class MainGameFrame:
pygame.draw.rect(self.display, package_color, pygame.draw.rect(self.display, package_color,
((pack_x * TILE_WIDTH) + 3, (pack_y * TILE_HEIGHT) + 3, TILE_WIDTH - 5, TILE_HEIGHT - 5)) ((pack_x * TILE_WIDTH) + 3, (pack_y * TILE_HEIGHT) + 3, TILE_WIDTH - 5, TILE_HEIGHT - 5))
def draw_nums(self):
for row in self.warehouse_map.tiles:
for cell in row:
if cell.category.name in self.warehouse_map.storage_types:
text_surface = self.font.render(str(cell.capacity), True, (0, 0, 0))
self.display.blit(text_surface, ((cell.x_position * TILE_WIDTH) + 1, (cell.y_position * TILE_HEIGHT) + 6))
def draw_agent(self): def draw_agent(self):
rotated = pygame.transform.rotate(self.agent_tex, DIRECTION_ANGLES.get(self.agent.direction)) rotated = pygame.transform.rotate(self.agent_tex, DIRECTION_ANGLES.get(self.agent.direction))
self.display.blit(rotated, (self.agent.x*TILE_WIDTH, self.agent.y*TILE_WIDTH)) self.display.blit(rotated, (self.agent.x*TILE_WIDTH, self.agent.y*TILE_WIDTH))

View File

@ -1,4 +1,4 @@
from attributes import PackSize, PackStatus from attributes import PackStatus
import random import random
import queue import queue
from collections import namedtuple from collections import namedtuple
@ -7,18 +7,17 @@ import itertools
Coordinates = namedtuple("Coordinates",'x y') Coordinates = namedtuple("Coordinates",'x y')
class CategoryData: class CategoryData:
def __init__(self, name, passable=False, can_store=True, location='general', pack_size=PackSize.ALL): def __init__(self, name, passable=False, can_store=True, location='general'):
self.name = name self.name = name
self.passable = passable self.passable = passable
self.can_store = can_store self.can_store = can_store
self.location = location self.location = location
self.pack_size = pack_size
def __repr__(self): def __repr__(self):
return self.name return self.name
class Pack: class Pack:
def __init__(self, size=PackSize.MEDIUM, categ='general', lays_on_field=None): def __init__(self, size=5, categ='general', lays_on_field=None):
self.size = size self.size = size
self.category = categ self.category = categ
assert isinstance(lays_on_field, Tile), AssertionError("Attribute lays_on_field must be a Tile object! You know, package cannot lay in void :)") assert isinstance(lays_on_field, Tile), AssertionError("Attribute lays_on_field must be a Tile object! You know, package cannot lay in void :)")
@ -27,16 +26,17 @@ class Pack:
def set_status(self): def set_status(self):
status = PackStatus.LOOSE status = PackStatus.LOOSE
if self.lays_on_field.category.name == 'Floor': if self.lays_on_field.category.name in ['Floor', 'FridgeFloor']:
status = PackStatus.LOOSE status = PackStatus.LOOSE
elif self.lays_on_field.category.name == 'Rack': elif self.lays_on_field.category.name in ['Rack', 'Fridge']:
status = PackStatus.STORED status = PackStatus.STORED
return status return status
CATEGORY = { CATEGORY = {
'floor': CategoryData('Floor', True, False), #lava 'floor': CategoryData('Floor', True, False), #lava
'rack': CategoryData('Rack', False, True), 'rack': CategoryData('Rack', False, True),
# 'freezer': CategoryData('Freezer', False, True, location='cold_room') 'fridge_floor': CategoryData('FridgeFloor', True, False, location='cold_room'),
'fridge': CategoryData('Fridge', False, True, location='cold_room')
} }
@ -46,9 +46,11 @@ class Warehouse:
self.height = length self.height = length
self.tiles = self.generate_map() self.tiles = self.generate_map()
self.no_of_racks = no_of_racks self.no_of_racks = no_of_racks
self.storage_types = ["Rack", "Fridge"]
self.no_of_packages = no_of_packages self.no_of_packages = no_of_packages
self.generate_racks() self.generate_racks()
self.open_isolated_areas() self.open_isolated_areas()
self.create_fridge(10)
self.packages = self.place_packages(no_of_packages) self.packages = self.place_packages(no_of_packages)
self.tiles[1][1] = Tile('floor', 1, 1) self.tiles[1][1] = Tile('floor', 1, 1)
def __str__(self): def __str__(self):
@ -68,7 +70,7 @@ class Warehouse:
node_x, node_y = random.randrange(1, self.width-1), random.randrange(1, self.height-1) node_x, node_y = random.randrange(1, self.width-1), random.randrange(1, self.height-1)
node = self.tiles[node_x][node_y] node = self.tiles[node_x][node_y]
next_node = None next_node = None
self.tiles[node_x][node_y] = Tile('rack', node_x, node_y) self.tiles[node_x][node_y] = Tile('rack', node_x, node_y, capacity=random.randrange(16, 20))
q.put(node) q.put(node)
while not q.empty(): while not q.empty():
if next_node is not None: if next_node is not None:
@ -92,6 +94,37 @@ class Warehouse:
node_y = next_node.y_position node_y = next_node.y_position
self.tiles[node_x][node_y] = Tile('rack', node_x, node_y) self.tiles[node_x][node_y] = Tile('rack', node_x, node_y)
def create_fridge(self, size):
x_corner = random.choice(['left', 'right'])
y_corner = random.choice(['top', 'bottom'])
start_x = None
start_y = None
end_x = None
end_y = None
if x_corner == 'left':
start_x = 0
end_x = size
else:
# import pdb
# pdb.set_trace()
start_x = (self.width-1) - size
end_x = self.width - 1
if y_corner == 'top':
start_y = 0
end_y = size
else:
start_y = (self.height-1) - size
end_y = self.height - 1
rows = self.tiles[start_x:end_x].copy()
for num, row in enumerate(rows, start_x):
for index, tile in enumerate(row[start_y:end_y], start_y):
if self.tiles[num][index].category.name == "Floor":
self.tiles[num][index] = Tile('fridge_floor', num, index)
else:
self.tiles[num][index] = Tile('fridge', num, index, capacity=random.randrange(10, 12))
def get_not_rack_nodes(self, node_x, node_y): def get_not_rack_nodes(self, node_x, node_y):
adjacent_tiles = self.get_adjacent_tiles(node_x, node_y) adjacent_tiles = self.get_adjacent_tiles(node_x, node_y)
possible_nodes = [line for line in adjacent_tiles if line.category.name != "Rack"] possible_nodes = [line for line in adjacent_tiles if line.category.name != "Rack"]
@ -161,8 +194,10 @@ class Warehouse:
for i in range(no_of_packages): for i in range(no_of_packages):
pack_x, pack_y = self._set_package_position() pack_x, pack_y = self._set_package_position()
package_field = self.tiles[pack_x][pack_y] package_field = self.tiles[pack_x][pack_y]
self.tiles[pack_x][pack_y].occupied = True
new_package = Pack(lays_on_field=package_field) new_package = Pack(lays_on_field=package_field)
new_package.size = random.randrange(1, 10)
if package_field.category.name in self.storage_types:
package_field.capacity -= new_package.size
packages.append(new_package) packages.append(new_package)
return packages return packages
def _set_package_position(self): def _set_package_position(self):
@ -203,11 +238,11 @@ class Warehouse:
return wall return wall
class Tile: class Tile:
def __init__(self, category, x_position, y_position): def __init__(self, category, x_position, y_position, capacity=10):
self.category = CATEGORY.get(category, CATEGORY['floor']) self.category = CATEGORY.get(category, CATEGORY['floor'])
self.x_position = x_position self.x_position = x_position
self.y_position = y_position self.y_position = y_position
self.occupied = False self.capacity = capacity
def __str__(self): def __str__(self):