301 lines
9.6 KiB
Python
301 lines
9.6 KiB
Python
#!/usr/bin/python3
|
|
from __future__ import annotations
|
|
import random
|
|
import threading
|
|
from queue import Queue
|
|
|
|
import pygame
|
|
import os
|
|
import time
|
|
from threading import Thread
|
|
from typing import Union
|
|
|
|
from app.base_field import BaseField
|
|
from app.board import Board
|
|
from app.utils import get_class
|
|
from app.fields import CROPS, PLANTS, SOILS, Sand, Clay
|
|
from config import *
|
|
|
|
from app.fields import Plant, Soil, Crops
|
|
|
|
|
|
class Tractor(BaseField):
|
|
def __init__(self, board: Board):
|
|
super().__init__(os.path.join(RESOURCE_DIR, f"{TRACTOR}.{PNG}"))
|
|
self.__pos_x = (int(HORIZONTAL_NUM_OF_FIELDS / 2) - 1) * FIELD_SIZE
|
|
self.__pos_y = (int(VERTICAL_NUM_OF_FIELDS / 2) - 1) * FIELD_SIZE
|
|
self.__direction = 0.0
|
|
self.__move = FIELD_SIZE
|
|
self.__board = board
|
|
self.__harvested_corps = []
|
|
self.__fuel = 10
|
|
|
|
def draw(self, screen: pygame.Surface):
|
|
self.draw_field(screen, self.__pos_x + FIELD_SIZE / 2, self.__pos_y + FIELD_SIZE / 2,
|
|
is_centered=True, size=(FIELD_SIZE, FIELD_SIZE), angle=self.__direction)
|
|
|
|
# Key methods handlers
|
|
def move(self):
|
|
if self.__direction == D_EAST:
|
|
self.move_right()
|
|
elif self.__direction == D_NORTH:
|
|
self.move_up()
|
|
elif self.__direction == D_WEST:
|
|
self.move_left()
|
|
else:
|
|
self.move_down()
|
|
|
|
def move_up(self):
|
|
if self.__pos_y - self.__move >= 0:
|
|
self.__pos_y -= self.__move
|
|
|
|
def move_down(self):
|
|
if self.__pos_y + self.__move + FIELD_SIZE <= HEIGHT:
|
|
self.__pos_y += self.__move
|
|
|
|
def move_left(self):
|
|
if self.__pos_x - self.__move >= 0:
|
|
self.__pos_x -= self.__move
|
|
|
|
def move_right(self):
|
|
if self.__pos_x + self.__move + FIELD_SIZE <= WIDTH:
|
|
self.__pos_x += self.__move
|
|
|
|
def direction_up(self):
|
|
self.__direction = 0
|
|
|
|
def direction_right(self):
|
|
self.__direction = 270
|
|
|
|
def direction_down(self):
|
|
self.__direction = 180
|
|
|
|
def direction_left(self):
|
|
self.__direction = 90
|
|
|
|
# def move(self):
|
|
# if self.__fuel > 0:
|
|
# self.__fuel -= 1
|
|
#
|
|
# if self.__direction == 0:
|
|
# if self.__pos_y - self.__move >= 0:
|
|
# self.__pos_y -= self.__move
|
|
#
|
|
# elif self.__direction == 270:
|
|
# if self.__pos_x + self.__move + FIELD_SIZE <= WIDTH:
|
|
# self.__pos_x += self.__move
|
|
#
|
|
# elif self.__direction == 180:
|
|
# if self.__pos_y + self.__move + FIELD_SIZE <= HEIGHT:
|
|
# self.__pos_y += self.__move
|
|
#
|
|
# elif self.__direction == 90:
|
|
# if self.__pos_x - self.__move >= 0:
|
|
# self.__pos_x -= self.__move
|
|
|
|
# else:
|
|
# print("Run out of fuel!")
|
|
|
|
def rotate_left(self):
|
|
self.__direction = (self.__direction - 90.0) % 360.0
|
|
|
|
def rotate_right(self):
|
|
self.__direction = (self.__direction + 90.0) % 360.0
|
|
|
|
def hydrate(self):
|
|
if self.check_field(Sand):
|
|
field = self.get_field_from_board()
|
|
if not field.is_hydrated and field.is_sowed:
|
|
print('Hydrate soil')
|
|
self.irrigate_sand(field)
|
|
elif self.check_field(Plant):
|
|
field = self.get_field_from_board()
|
|
if not field.is_hydrated:
|
|
print("Hydrate plant")
|
|
self.irrigate_plants(field)
|
|
|
|
def hydrate_sand(self):
|
|
if self.check_field(Sand):
|
|
field = self.get_field_from_board()
|
|
if not field.is_hydrated and field.is_sowed:
|
|
print('Hydrate soil')
|
|
self.irrigate_sand(field)
|
|
|
|
def hydrate_plant(self):
|
|
if self.check_field(Plant):
|
|
field = self.get_field_from_board()
|
|
if not field.is_hydrated:
|
|
print("Hydrate plant")
|
|
self.irrigate_plants(field)
|
|
|
|
def sow(self):
|
|
field = self.get_field_from_board()
|
|
if self.check_field(Sand) and not field.is_sowed:
|
|
print('Sow')
|
|
field.is_sowed = True
|
|
|
|
def harvest(self):
|
|
if self.check_field(Crops):
|
|
print('Harvest')
|
|
field = self.get_field_from_board()
|
|
self.harvest_crops(field)
|
|
self.get_result_of_harvesting()
|
|
|
|
def fertilize(self):
|
|
if self.check_field(Clay):
|
|
print('Fertilize soil')
|
|
field = self.get_field_from_board()
|
|
self.fertilize_clay(field)
|
|
|
|
################################################################################
|
|
|
|
def fertilize_clay(self, field: Clay):
|
|
field.is_fertilized = True
|
|
self.do_action((Sand.__name__,))
|
|
|
|
def irrigate_plants(self, field: Plant):
|
|
field.is_hydrated = True
|
|
# self.do_time_action(CROPS)
|
|
self.do_action(CROPS)
|
|
|
|
def irrigate_sand(self, field: Sand):
|
|
field.is_hydrated = True
|
|
# self.do_time_action(PLANTS)
|
|
self.do_action(PLANTS)
|
|
|
|
def harvest_crops(self, field: Crops):
|
|
self.__harvested_corps.append(type(field).__name__)
|
|
self.do_action(SOILS)
|
|
|
|
def do_action(self, TYPE: tuple):
|
|
choosen_type = random.choice(TYPE)
|
|
obj = get_class("app.fields", choosen_type)
|
|
x, y = self.get_position()
|
|
self.__board.get_fields()[x][y] = obj()
|
|
|
|
def do_time_action(self, TYPE: tuple):
|
|
thread = Thread(target=self.do_time_action_handler, args=(TYPE,), daemon=True)
|
|
thread.start()
|
|
|
|
def do_time_action_handler(self, TYPE: tuple):
|
|
time.sleep(TIME_OF_GROWING)
|
|
self.do_action(TYPE)
|
|
|
|
def check_field(self, class_name: Union[type(Plant), type(Crops), type(Soil)]):
|
|
if isinstance(self.get_field_from_board(), class_name):
|
|
return True
|
|
return False
|
|
|
|
def get_field_from_board(self):
|
|
x, y = self.get_position()
|
|
return self.__board.get_fields()[x][y]
|
|
|
|
def get_field_from_board_by_positions(self, x, y):
|
|
return self.__board.get_fields()[x][y]
|
|
|
|
def get_position(self):
|
|
x = self.__pos_x // FIELD_SIZE
|
|
y = self.__pos_y // FIELD_SIZE
|
|
return x, y
|
|
|
|
def get_result_of_harvesting(self):
|
|
crops = set(self.__harvested_corps)
|
|
result = 0.0
|
|
for crop in crops:
|
|
amount = self.__harvested_corps.count(crop)
|
|
print(f"{amount} x {crop}")
|
|
result += amount * get_class("app.fields", crop).price
|
|
|
|
print(f"Price for collected crops: {result:.2f}")
|
|
|
|
def __str__(self):
|
|
x, y = self.get_position()
|
|
return f"Position: {x}:{y} - {type(self.__board.get_fields()[x][y]).__name__}"
|
|
|
|
def get_direction(self):
|
|
return self.__direction
|
|
|
|
def move_by_bfs_handler(self, moves: list[tuple[str, str]], is_running: threading.Event):
|
|
thread = threading.Thread(target=self.move_by_bfs, args=(moves, is_running), daemon=True)
|
|
thread.start()
|
|
|
|
def move_by_bfs(self, moves: list[tuple[str, str]], is_running: threading.Event):
|
|
print(moves)
|
|
print(f"Length of Moves {len(moves)} - {3 ** len(moves)}")
|
|
while len(moves) > 0:
|
|
movement, action = moves.pop(0)
|
|
# do action
|
|
time.sleep(0.5)
|
|
print(f"Action {action}")
|
|
if action == A_FERTILIZE:
|
|
self.fertilize()
|
|
elif action == A_SOW:
|
|
self.sow()
|
|
self.hydrate()
|
|
elif action == A_HYDRATE:
|
|
self.hydrate()
|
|
elif action == A_HARVEST:
|
|
self.harvest()
|
|
time.sleep(1)
|
|
|
|
# move
|
|
print(f"Move {movement}")
|
|
if movement == M_GO_FORWARD:
|
|
self.move()
|
|
elif movement == M_ROTATE_LEFT:
|
|
self.rotate_left()
|
|
elif movement == M_ROTATE_RIGHT:
|
|
self.rotate_right()
|
|
|
|
time.sleep(TIME_OF_MOVING)
|
|
is_running.clear()
|
|
|
|
@staticmethod
|
|
def move_is_correct(x: int, y: int, direction: float) -> Union[(int, int), None]:
|
|
pos_x = x * FIELD_SIZE
|
|
pos_y = y * FIELD_SIZE
|
|
|
|
if direction == D_NORTH and pos_y - FIELD_SIZE >= 0:
|
|
return x, y - 1
|
|
if direction == D_SOUTH and pos_y + 2 * FIELD_SIZE <= HEIGHT:
|
|
return x, y + 1
|
|
if direction == D_WEST and pos_x - FIELD_SIZE >= 0:
|
|
return x - 1, y
|
|
if direction == D_EAST and pos_x + 2 * FIELD_SIZE <= WIDTH:
|
|
return x + 1, y
|
|
|
|
return None
|
|
|
|
@staticmethod
|
|
def fertilize_clay_succ(field: Clay, board: Board, x: int, y: int):
|
|
field.is_fertilized = True
|
|
return Tractor.do_action_succ(board, x, y, (Sand.__name__,))
|
|
|
|
@staticmethod
|
|
def sow_succ(field: Sand):
|
|
field.is_sowed = True
|
|
return field
|
|
|
|
@staticmethod
|
|
def irrigate_plants_succ(field: Plant, board: Board, x: int, y: int):
|
|
field.is_hydrated = True
|
|
return Tractor.do_action_succ(board, x, y, CROPS)
|
|
|
|
@staticmethod
|
|
def irrigate_sand_succ(field: Sand, board: Board, x: int, y: int):
|
|
field.is_hydrated = True
|
|
return Tractor.do_action_succ(board, x, y, PLANTS)
|
|
|
|
@staticmethod
|
|
def harvest_crops_succ(board: Board, x: int, y: int):
|
|
# Tractor.__harvested_corps.append(type(field).__name__)
|
|
return Tractor.do_action_succ(board, x, y, SOILS)
|
|
|
|
@staticmethod
|
|
def do_action_succ(board: Board, x: int, y: int, types: tuple):
|
|
choosen_type = random.choice(types)
|
|
obj = get_class("app.fields", choosen_type)
|
|
board.get_fields()[x][y] = obj()
|
|
return obj()
|
|
# return f"Position: {x}:{y} - {type(self.__board.get_fields()[x][y]).__name__}\nFuel: {self.__fuel}\n"
|