129 lines
4.2 KiB
Python
129 lines
4.2 KiB
Python
import json
|
|
import agent as ag
|
|
import project_constants as const
|
|
import tile as tl
|
|
from mine_models import standard_mine as sm
|
|
from mine_models import time_mine as tm
|
|
from mine_models import chained_mine as cm
|
|
|
|
|
|
tile_asset_options = {
|
|
"BLUE": const.ASSET_TILE_BLUE,
|
|
"GREEN": const.ASSET_TILE_GREEN,
|
|
"ORANGE": const.ASSET_TILE_ORANGE,
|
|
"PURPLE": const.ASSET_TILE_PURPLE,
|
|
"RED": const.ASSET_TILE_RED,
|
|
"WHITE": const.ASSET_TILE_WHITE,
|
|
"YELLOW": const.ASSET_TILE_YELLOW
|
|
}
|
|
|
|
mine_asset_options = {
|
|
'A': const.ASSET_MINE_A,
|
|
'B': const.ASSET_MINE_B,
|
|
'F': const.ASSET_MINE_F,
|
|
'K': const.ASSET_MINE_K
|
|
}
|
|
|
|
|
|
class Minefield:
|
|
def __init__(self, json_path):
|
|
self.turn = 0
|
|
|
|
self.agent = ag.Agent(const.MAP_RANDOM_10x10)
|
|
|
|
# open JSON with minefield info
|
|
with open(json_path) as json_data:
|
|
data = json.load(json_data)
|
|
|
|
# create matrix of a desired size, fill it with default tile objects
|
|
self.matrix = [
|
|
[
|
|
tl.Tile((row, column)) for column in range(const.V_GRID_HOR_TILES)
|
|
] for row in range(const.V_GRID_VER_TILES)
|
|
]
|
|
|
|
# iterate through tiles, set their colors and add mines
|
|
for row in range(const.V_GRID_VER_TILES):
|
|
for column in range(const.V_GRID_HOR_TILES):
|
|
|
|
# load tile's data from json
|
|
tile_data = data[f"{row},{column}"]
|
|
|
|
# if there is a mine, create & assign new Mine object (type recognition included)
|
|
if tile_data["mine"] is not None:
|
|
mine = self._create_mine(tile_data["mine"], row, column)
|
|
self.matrix[row][column].mine = mine
|
|
|
|
self.matrix[row][column].color = tile_data["color"].upper()
|
|
|
|
@staticmethod
|
|
def calculate_screen_position(row, column):
|
|
coords = (
|
|
const.V_SCREEN_PADDING + const.V_TILE_SIZE * column,
|
|
const.V_SCREEN_PADDING + const.V_TILE_SIZE * row,
|
|
)
|
|
|
|
return coords
|
|
|
|
def draw(self, window):
|
|
# iterate through tiles
|
|
for row in self.matrix:
|
|
for tile in row:
|
|
|
|
# calculate tile position on the screen
|
|
tile_screen_coords = self.calculate_screen_position(tile.position[0], tile.position[1])
|
|
|
|
# draw a tile
|
|
window.blit(tile_asset_options.get(tile.color), tile_screen_coords)
|
|
|
|
# draw a mine on top if there is one
|
|
if tile.mine is not None:
|
|
# TODO: blit appropriate mine type
|
|
# current icons don't represent actual types, thus every mine has the same icon (temporary solution)
|
|
window.blit(mine_asset_options['A'], tile_screen_coords)
|
|
|
|
# draw the sapper has been moved to main
|
|
|
|
# ================ #
|
|
# === MOVEMENT === #
|
|
# ================ #
|
|
|
|
# check if sapper's destination is accessible
|
|
# If Agent comes upon a tile with a mine his starting position shall be reestablished
|
|
def is_valid_move(self, target_row: int, target_column: int):
|
|
if 0 <= target_row < const.V_GRID_VER_TILES \
|
|
and 0 <= target_column < const.V_GRID_HOR_TILES \
|
|
and self.matrix[target_row][target_column] is None:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
# distinguishes new mine's type and creates appropriate object
|
|
def _create_mine(self, mine_data, row, column):
|
|
mine_type = mine_data["mine_type"]
|
|
|
|
# TIME MINE
|
|
if mine_type == "time":
|
|
timer = mine_data["timer"]
|
|
mine = tm.TimeMine((row, column), int(timer))
|
|
|
|
# CHAINED MINE
|
|
elif mine_type == "chained":
|
|
if mine_data["predecessor"] is not None:
|
|
# locate predecessor
|
|
row, column = map(int, mine_data["predecessor"].split(','))
|
|
|
|
# get predecessor object and assign it to the new mine
|
|
predecessor = self.matrix[row][column].mine
|
|
mine = cm.ChainedMine((row, column), predecessor)
|
|
|
|
else:
|
|
mine = cm.ChainedMine((row, column))
|
|
|
|
# STANDARD MINE
|
|
else:
|
|
mine = sm.StandardMine((row, column))
|
|
|
|
return mine
|