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 queue import PriorityQueue
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 sys
@ -89,7 +89,16 @@ class Agent:
def heuristic(self, start: Node, goal: Node):
diff_x = pow(goal.x - start.x, 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):
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):
weight = package.size
accepted_weights = [weight, PackSize.ALL]
start_node = Node(self.x, self.y)
quarter_x = int(self.warehouse.width/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
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_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]
racks_costs = []
for rack in quarter_racks:
@ -208,7 +216,9 @@ class Agent:
def pick_up_package(self, pack):
self.warehouse.packages.remove(pack)
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
pack.lays_on_field = None
self.transported_package = pack
@ -219,6 +229,6 @@ class Agent:
self.transported_package = None
self.is_loaded = False
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
self.warehouse.packages.append(pack)
self.warehouse.packages.append(pack)

View File

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

19
main.py
View File

@ -3,14 +3,16 @@ import warehouse
import agent
import random
import sys
from attributes import PackSize, PackStatus, COLORS, DIRECTION_ANGLES
from attributes import PackStatus, COLORS, DIRECTION_ANGLES
WINDOW_SIZE = (640, 640)
COLOR_OF_FIELD = {
'Floor': 'gray',
'Rack': 'white',
'Pack': 'yellow',
'path': 'orange'
'path': 'orange',
'FridgeFloor': 'lightblue',
'Fridge': 'iceblue'
}
TILE_WIDTH = 32
TILE_HEIGHT = 32
@ -18,9 +20,12 @@ CIRCLE_CENTER_X, CIRCLE_CENTER_Y = int(TILE_WIDTH/2), int(TILE_HEIGHT/2)
class MainGameFrame:
def __init__(self):
pygame.font.init()
self.display = pygame.display.set_mode(WINDOW_SIZE)
pygame.display.set_caption("Smart ForkLift")
agent_radius = int(TILE_WIDTH/2)
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)
starting_x, starting_y = self.set_starting_agent_position()
self.agent = agent.Agent(starting_x, starting_y, self.warehouse_map, agent_radius)
@ -35,6 +40,7 @@ class MainGameFrame:
self.draw_floor()
self.draw_packages()
self.draw_agent()
self.draw_nums()
self.agent.move()
pygame.display.update()
self.clock.tick(8)
@ -52,8 +58,6 @@ class MainGameFrame:
def draw_field(self, 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 = COLORS[color]
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,
((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):
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))

View File

@ -1,4 +1,4 @@
from attributes import PackSize, PackStatus
from attributes import PackStatus
import random
import queue
from collections import namedtuple
@ -7,18 +7,17 @@ import itertools
Coordinates = namedtuple("Coordinates",'x y')
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.passable = passable
self.can_store = can_store
self.location = location
self.pack_size = pack_size
def __repr__(self):
return self.name
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.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 :)")
@ -27,16 +26,17 @@ class Pack:
def set_status(self):
status = PackStatus.LOOSE
if self.lays_on_field.category.name == 'Floor':
if self.lays_on_field.category.name in ['Floor', 'FridgeFloor']:
status = PackStatus.LOOSE
elif self.lays_on_field.category.name == 'Rack':
elif self.lays_on_field.category.name in ['Rack', 'Fridge']:
status = PackStatus.STORED
return status
CATEGORY = {
'floor': CategoryData('Floor', True, False), #lava
'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.tiles = self.generate_map()
self.no_of_racks = no_of_racks
self.storage_types = ["Rack", "Fridge"]
self.no_of_packages = no_of_packages
self.generate_racks()
self.open_isolated_areas()
self.create_fridge(10)
self.packages = self.place_packages(no_of_packages)
self.tiles[1][1] = Tile('floor', 1, 1)
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 = self.tiles[node_x][node_y]
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)
while not q.empty():
if next_node is not None:
@ -92,6 +94,37 @@ class Warehouse:
node_y = next_node.y_position
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):
adjacent_tiles = self.get_adjacent_tiles(node_x, node_y)
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):
pack_x, pack_y = self._set_package_position()
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.size = random.randrange(1, 10)
if package_field.category.name in self.storage_types:
package_field.capacity -= new_package.size
packages.append(new_package)
return packages
def _set_package_position(self):
@ -203,11 +238,11 @@ class Warehouse:
return wall
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.x_position = x_position
self.y_position = y_position
self.occupied = False
self.capacity = capacity
def __str__(self):