add loader map
This commit is contained in:
parent
61fa6d90c5
commit
d62d11f58b
35
Readme.md
35
Readme.md
@ -2,7 +2,7 @@
|
|||||||
### 1. Requirements
|
### 1. Requirements
|
||||||
python version 3.9 or higher
|
python version 3.9 or higher
|
||||||
```bash
|
```bash
|
||||||
python -v
|
python3 -v
|
||||||
```
|
```
|
||||||
### 2. Create virtual environments and install libs
|
### 2. Create virtual environments and install libs
|
||||||
```bash
|
```bash
|
||||||
@ -14,3 +14,36 @@ pip3 install -r requirements.txt
|
|||||||
```bash
|
```bash
|
||||||
python3 main.py
|
python3 main.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 4. Arguments
|
||||||
|
Maps are saved in maps directory with json format.\
|
||||||
|
It's two dimensional array of types of fields. \
|
||||||
|
Example:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
["Corn", "Sunflower","Clay"],
|
||||||
|
["Clay", "Soil","Clay"],
|
||||||
|
["Sunflower", "Soil","Corn"]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
Warning!
|
||||||
|
Map must the same sizes what loaded map!\
|
||||||
|
Change sizes map in config.py
|
||||||
|
```python
|
||||||
|
# Board settings:
|
||||||
|
VERTICAL_NUM_OF_FIELDS = 3
|
||||||
|
HORIZONTAL_NUM_OF_FIELDS = 3
|
||||||
|
```
|
||||||
|
\
|
||||||
|
#####4.1 Save generated map:
|
||||||
|
```bash
|
||||||
|
python main.py --save-map
|
||||||
|
```
|
||||||
|
Map will be saved in maps directory.
|
||||||
|
Generated filename: map-uuid
|
||||||
|
|
||||||
|
#####4.2 Load map
|
||||||
|
```bash
|
||||||
|
python main.py --load-map=name_of_map
|
||||||
|
```
|
||||||
|
Map must be in the maps directory with json extension.
|
@ -6,6 +6,7 @@ from threading import Event
|
|||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
from config import *
|
from config import *
|
||||||
|
from app.cmd_parser import Arg
|
||||||
from app.graphsearch import Node
|
from app.graphsearch import Node
|
||||||
from app.board import Board
|
from app.board import Board
|
||||||
from app.tractor import Tractor
|
from app.tractor import Tractor
|
||||||
@ -14,11 +15,11 @@ from app.bfs import Bfs
|
|||||||
|
|
||||||
|
|
||||||
class App:
|
class App:
|
||||||
def __init__(self):
|
def __init__(self, args: list[Arg]):
|
||||||
self.__running = True
|
self.__running = True
|
||||||
self.__screen = None
|
self.__screen = None
|
||||||
self.__clock = None
|
self.__clock = None
|
||||||
self.__board = Board()
|
self.__board = Board(args=args)
|
||||||
self.__tractor = Tractor(self.__board)
|
self.__tractor = Tractor(self.__board)
|
||||||
self.__bot_is_running = Event()
|
self.__bot_is_running = Event()
|
||||||
self.__moves = None
|
self.__moves = None
|
||||||
|
67
app/board.py
67
app/board.py
@ -1,21 +1,30 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
import copy
|
import copy
|
||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
|
||||||
import pygame
|
import pygame
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
from app import Arg
|
||||||
from app.fields import *
|
from app.fields import *
|
||||||
from app.utils import get_class
|
from app.utils import get_class
|
||||||
|
|
||||||
|
|
||||||
class Board:
|
class Board:
|
||||||
def __init__(self, fields=None):
|
def __init__(self, fields=None, args: list[Arg] = None):
|
||||||
if fields is None:
|
if fields is None:
|
||||||
fields = []
|
fields = []
|
||||||
self.__fields = fields
|
self.__fields = fields
|
||||||
self.create_board()
|
self.create_board()
|
||||||
self.fill()
|
self.fill()
|
||||||
self.generate_board()
|
self.generate_board()
|
||||||
|
if args is not None:
|
||||||
|
for arg in args:
|
||||||
|
if arg.get_arg_name() == SAVE_MAP:
|
||||||
|
self.save_map()
|
||||||
|
elif arg.get_arg_name() == LOAD_MAP:
|
||||||
|
self.load_map(arg.get_value())
|
||||||
# print(self.__fields)
|
# print(self.__fields)
|
||||||
|
|
||||||
def get_fields(self) -> list:
|
def get_fields(self) -> list:
|
||||||
@ -56,3 +65,59 @@ class Board:
|
|||||||
for j in range(VERTICAL_NUM_OF_FIELDS):
|
for j in range(VERTICAL_NUM_OF_FIELDS):
|
||||||
print(f"{j} - {type(self.__fields[i][j]).__name__}", end=" | ")
|
print(f"{j} - {type(self.__fields[i][j]).__name__}", end=" | ")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
def convert_fields_to_list_of_types(self) -> list:
|
||||||
|
data = []
|
||||||
|
for i in range(HORIZONTAL_NUM_OF_FIELDS):
|
||||||
|
data.append([])
|
||||||
|
for j in range(VERTICAL_NUM_OF_FIELDS):
|
||||||
|
data[i].append(type(self.__fields[i][j]).__name__)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def convert_dict_map_to_list_map(self, dict_map: dict) -> list:
|
||||||
|
list_map = []
|
||||||
|
for col in dict_map.values():
|
||||||
|
list_map.append(copy.copy(col))
|
||||||
|
return list_map
|
||||||
|
|
||||||
|
def load_map(self, filename: str):
|
||||||
|
try:
|
||||||
|
with open(os.path.join(MAP_DIR,f"{filename}.{JSON}")) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
except IOError:
|
||||||
|
raise IOError(f"Cannot load file: {filename}.{JSON}!")
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
raise Exception("Cannot load json file")
|
||||||
|
|
||||||
|
size_flag = True
|
||||||
|
# print(data)
|
||||||
|
if len(data) != HORIZONTAL_NUM_OF_FIELDS:
|
||||||
|
size_flag = False
|
||||||
|
for fields in data:
|
||||||
|
if len(fields) != VERTICAL_NUM_OF_FIELDS:
|
||||||
|
size_flag = False
|
||||||
|
if not size_flag:
|
||||||
|
raise Exception('Cannot load map! Incorrect size of map')
|
||||||
|
print("Map was successfully loaded!")
|
||||||
|
|
||||||
|
# init map
|
||||||
|
for x in range(len(data)):
|
||||||
|
for y in range(len(data[x])):
|
||||||
|
field_type = data[x][y]
|
||||||
|
# print(field_type)
|
||||||
|
c = get_class("app.fields", field_type)
|
||||||
|
self.__fields[x][y] = c()
|
||||||
|
print("Map was successfully initialized!")
|
||||||
|
|
||||||
|
def save_map(self) -> None:
|
||||||
|
if len(self.__fields) == 0:
|
||||||
|
raise Exception('Board is not initialized!')
|
||||||
|
|
||||||
|
fields = self.convert_fields_to_list_of_types()
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(os.path.join(MAP_DIR,f"{MAP_FILE_NAME}-{uuid.uuid4().hex}.{JSON}"), 'w') as f:
|
||||||
|
json.dump(fields, f)
|
||||||
|
except IOError:
|
||||||
|
raise IOError(f"Cannot save file:!")
|
||||||
|
43
app/cmd_parser.py
Normal file
43
app/cmd_parser.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import sys
|
||||||
|
from config import *
|
||||||
|
|
||||||
|
|
||||||
|
class Arg:
|
||||||
|
def __init__(self, arg_name: str, value: str = None):
|
||||||
|
self.__arg_name = arg_name
|
||||||
|
self.__value = value
|
||||||
|
|
||||||
|
def get_arg_name(self) -> str:
|
||||||
|
return self.__arg_name
|
||||||
|
|
||||||
|
def get_value(self) -> str:
|
||||||
|
return self.__value
|
||||||
|
|
||||||
|
|
||||||
|
class CommandLineParser:
|
||||||
|
@staticmethod
|
||||||
|
def parse() -> list:
|
||||||
|
args = sys.argv[1:]
|
||||||
|
|
||||||
|
results = []
|
||||||
|
|
||||||
|
if len(args) > 0:
|
||||||
|
for arg in args:
|
||||||
|
if arg == SAVE_MAP:
|
||||||
|
print("Saving map")
|
||||||
|
results.append(Arg(SAVE_MAP))
|
||||||
|
|
||||||
|
elif arg.find(LOAD_MAP, 0, len(LOAD_MAP)-1):
|
||||||
|
cmd = arg.split("=")
|
||||||
|
if len(cmd) == 2:
|
||||||
|
# print(cmd)
|
||||||
|
map_name = cmd[1]
|
||||||
|
print(f"Loading map: {map_name}")
|
||||||
|
results.append(Arg(LOAD_MAP, map_name))
|
||||||
|
else:
|
||||||
|
raise Exception(f"Incorrect name of map: {cmd}!")
|
||||||
|
else:
|
||||||
|
raise Exception(f"Unknown arg {arg}")
|
||||||
|
# print(args)
|
||||||
|
|
||||||
|
return results
|
17
config.py
17
config.py
@ -5,14 +5,14 @@ import os
|
|||||||
__all__ = (
|
__all__ = (
|
||||||
'WIDTH', 'HEIGHT', 'FIELD_SIZE', 'TIME_OF_MOVING',
|
'WIDTH', 'HEIGHT', 'FIELD_SIZE', 'TIME_OF_MOVING',
|
||||||
'VERTICAL_NUM_OF_FIELDS', 'HORIZONTAL_NUM_OF_FIELDS',
|
'VERTICAL_NUM_OF_FIELDS', 'HORIZONTAL_NUM_OF_FIELDS',
|
||||||
'FPS', 'CAPTION', 'RESOURCE_DIR', 'TRACTOR', 'PNG',
|
'FPS', 'CAPTION', 'RESOURCE_DIR', 'MAP_DIR', 'TRACTOR', 'PNG',
|
||||||
'SAND', 'CLAY', 'GRASS', 'CORN', 'SUNFLOWER',
|
'SAND', 'CLAY', 'GRASS', 'CORN', 'SUNFLOWER',
|
||||||
'FIELD_TYPES', 'TIME_OF_GROWING', 'AMOUNT_OF_CROPS',
|
'FIELD_TYPES', 'TIME_OF_GROWING', 'AMOUNT_OF_CROPS',
|
||||||
'M_GO_FORWARD', 'M_ROTATE_LEFT', 'M_ROTATE_RIGHT',
|
'M_GO_FORWARD', 'M_ROTATE_LEFT', 'M_ROTATE_RIGHT',
|
||||||
'A_SOW', 'A_HARVEST', 'A_HYDRATE', 'A_FERTILIZE', 'A_DO_NOTHING',
|
'A_SOW', 'A_HARVEST', 'A_HYDRATE', 'A_FERTILIZE', 'A_DO_NOTHING',
|
||||||
'D_NORTH', 'D_EAST', 'D_SOUTH', 'D_WEST',
|
'D_NORTH', 'D_EAST', 'D_SOUTH', 'D_WEST',
|
||||||
'VALUE_OF_CROPS', 'VALUE_OF_PLANT',
|
'VALUE_OF_CROPS', 'VALUE_OF_PLANT', 'VALUE_OF_SAND', 'VALUE_OF_CLAY',
|
||||||
'VALUE_OF_SAND', 'VALUE_OF_CLAY'
|
'MAP_FILE_NAME', 'JSON','SAVE_MAP', 'LOAD_MAP'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Board settings:
|
# Board settings:
|
||||||
@ -29,10 +29,15 @@ CAPTION = 'Tractor'
|
|||||||
# Path
|
# Path
|
||||||
BASE_DIR = os.path.dirname(__file__)
|
BASE_DIR = os.path.dirname(__file__)
|
||||||
RESOURCE_DIR = os.path.join(BASE_DIR, 'resources')
|
RESOURCE_DIR = os.path.join(BASE_DIR, 'resources')
|
||||||
|
MAP_DIR = os.path.join(BASE_DIR, 'maps')
|
||||||
|
MAP_FILE_NAME = 'map'
|
||||||
|
|
||||||
# Picture format
|
# Picture format
|
||||||
PNG = "png"
|
PNG = "png"
|
||||||
|
|
||||||
|
# File format
|
||||||
|
JSON = 'json'
|
||||||
|
|
||||||
# Tractor settings
|
# Tractor settings
|
||||||
TRACTOR = 'tractor'
|
TRACTOR = 'tractor'
|
||||||
|
|
||||||
@ -68,10 +73,14 @@ A_DO_NOTHING = "do nothing"
|
|||||||
|
|
||||||
# Costs fields:
|
# Costs fields:
|
||||||
VALUE_OF_CROPS = 1
|
VALUE_OF_CROPS = 1
|
||||||
VALUE_OF_PLANT = 3
|
VALUE_OF_PLANT = 4
|
||||||
VALUE_OF_SAND = 7
|
VALUE_OF_SAND = 7
|
||||||
VALUE_OF_CLAY = 10
|
VALUE_OF_CLAY = 10
|
||||||
|
|
||||||
# Times
|
# Times
|
||||||
TIME_OF_GROWING = 2
|
TIME_OF_GROWING = 2
|
||||||
TIME_OF_MOVING = 2
|
TIME_OF_MOVING = 2
|
||||||
|
|
||||||
|
# Args
|
||||||
|
SAVE_MAP = '--save-map'
|
||||||
|
LOAD_MAP = '--load-map'
|
||||||
|
4
main.py
4
main.py
@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
from app import App
|
from app import App
|
||||||
|
from app.cmd_parser import CommandLineParser
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app = App()
|
args = CommandLineParser.parse()
|
||||||
|
app = App(args)
|
||||||
app.run()
|
app.run()
|
||||||
|
1
maps/map-1.json
Normal file
1
maps/map-1.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[["Sunflower", "Corn", "Sand", "Sand", "Sand", "Sand", "Corn", "Sand", "Sunflower"], ["Grass", "Clay", "Clay", "Grass", "Grass", "Grass", "Corn", "Clay", "Sand"], ["Grass", "Clay", "Sunflower", "Corn", "Sand", "Sunflower", "Grass", "Corn", "Sand"], ["Grass", "Clay", "Corn", "Sand", "Sunflower", "Sand", "Grass", "Clay", "Grass"], ["Clay", "Corn", "Grass", "Sunflower", "Sunflower", "Corn", "Sunflower", "Grass", "Sand"], ["Clay", "Corn", "Corn", "Clay", "Corn", "Corn", "Grass", "Clay", "Clay"], ["Sand", "Sunflower", "Grass", "Corn", "Grass", "Sunflower", "Sand", "Sunflower", "Sand"], ["Corn", "Corn", "Sand", "Sunflower", "Sand", "Sand", "Clay", "Sunflower", "Sand"], ["Sunflower", "Corn", "Clay", "Sunflower", "Sunflower", "Sunflower", "Sunflower", "Sunflower", "Clay"], ["Grass", "Grass", "Corn", "Sand", "Sunflower", "Clay", "Clay", "Clay", "Sand"], ["Grass", "Clay", "Sand", "Corn", "Clay", "Corn", "Clay", "Corn", "Corn"], ["Corn", "Corn", "Grass", "Clay", "Sunflower", "Grass", "Sand", "Sand", "Sand"]]
|
1
maps/map-2.json
Normal file
1
maps/map-2.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[["Corn", "Sunflower", "Corn", "Sand", "Grass", "Sunflower", "Sunflower", "Clay", "Sand"], ["Clay", "Sand", "Clay", "Grass", "Sand", "Clay", "Corn", "Sunflower", "Sand"], ["Sand", "Grass", "Grass", "Corn", "Grass", "Sand", "Corn", "Sunflower", "Clay"], ["Clay", "Sand", "Sunflower", "Sand", "Sunflower", "Corn", "Sunflower", "Corn", "Clay"], ["Corn", "Corn", "Clay", "Sand", "Clay", "Grass", "Clay", "Clay", "Grass"], ["Grass", "Sand", "Corn", "Sand", "Sand", "Sunflower", "Clay", "Sand", "Clay"], ["Sunflower", "Sand", "Grass", "Sand", "Sand", "Grass", "Grass", "Sand", "Corn"], ["Clay", "Sand", "Corn", "Sand", "Sunflower", "Clay", "Sunflower", "Grass", "Corn"], ["Sand", "Grass", "Sand", "Sand", "Clay", "Grass", "Sunflower", "Corn", "Corn"], ["Sand", "Sand", "Grass", "Grass", "Sand", "Corn", "Grass", "Sunflower", "Sand"], ["Clay", "Grass", "Clay", "Sand", "Grass", "Sunflower", "Corn", "Clay", "Sunflower"], ["Grass", "Grass", "Clay", "Corn", "Grass", "Clay", "Grass", "Clay", "Corn"]]
|
1
maps/map-3.json
Normal file
1
maps/map-3.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[["Corn", "Grass", "Sand", "Corn", "Sand", "Clay", "Sunflower", "Corn", "Sunflower"], ["Sand", "Clay", "Clay", "Sunflower", "Sand", "Grass", "Corn", "Grass", "Sunflower"], ["Sunflower", "Clay", "Sunflower", "Sunflower", "Sand", "Sand", "Grass", "Corn", "Sand"], ["Sunflower", "Sunflower", "Grass", "Clay", "Sunflower", "Grass", "Sunflower", "Sunflower", "Grass"], ["Sunflower", "Corn", "Grass", "Sunflower", "Corn", "Corn", "Sand", "Corn", "Sunflower"], ["Clay", "Corn", "Corn", "Grass", "Sunflower", "Corn", "Grass", "Clay", "Corn"], ["Sand", "Sunflower", "Grass", "Grass", "Grass", "Clay", "Sand", "Sand", "Clay"], ["Sunflower", "Clay", "Grass", "Clay", "Corn", "Grass", "Grass", "Sand", "Sunflower"], ["Clay", "Corn", "Clay", "Grass", "Grass", "Sunflower", "Sand", "Corn", "Sand"], ["Sunflower", "Clay", "Grass", "Sand", "Clay", "Sunflower", "Corn", "Clay", "Sand"], ["Corn", "Sunflower", "Clay", "Clay", "Grass", "Sunflower", "Sand", "Corn", "Sunflower"], ["Grass", "Grass", "Corn", "Clay", "Sand", "Clay", "Grass", "Corn", "Sand"]]
|
Loading…
Reference in New Issue
Block a user