221 lines
9.8 KiB
Python
221 lines
9.8 KiB
Python
import random
|
|
import pygame
|
|
import sys
|
|
import pathfinder
|
|
import time
|
|
from decisiontree import DecisionTree
|
|
from imagerecognizer import ImageRecognizer
|
|
from objects import Grass
|
|
from objects import Mine
|
|
from objects import Rock
|
|
from objects import Puddle
|
|
|
|
|
|
MARGIN = 20 # marginesy - odległość kraty od końca okna
|
|
SQUARE_HEIGHT = 35
|
|
SQUARE_WIDTH = 35
|
|
CENTER_DIST = 38 # odległość pomiędzy środkami kwadratów
|
|
BOARDCOLS = 15 # liczba kolumn planszy
|
|
BOARDROWS = BOARDCOLS # liczba wierszy planszy
|
|
WINDOW_HEIGHT = BOARDCOLS * CENTER_DIST + (2 * MARGIN)
|
|
WINDOW_WIDTH = BOARDROWS * CENTER_DIST + (2 * MARGIN)
|
|
|
|
|
|
class Field: # obiekt clasy field jest pojedynczym polem planszy
|
|
def __init__(self, coordinates, color, fieldty):
|
|
Board.fields.append(self)
|
|
self.rect = pygame.Rect(coordinates[0], coordinates[1], SQUARE_WIDTH, SQUARE_HEIGHT)
|
|
self.color = color
|
|
self.type = fieldty
|
|
self.object = self.assign_object()
|
|
self.deley_value = self.object.deley
|
|
self.redisp = True
|
|
|
|
def assign_object(self):
|
|
if self.type == 'T':
|
|
object = Grass(self.rect.center[0],self.rect.center[1], SQUARE_WIDTH, SQUARE_HEIGHT)
|
|
return object
|
|
if self.type == 'P':
|
|
object = Puddle(self.rect.center[0],self.rect.center[1],SQUARE_WIDTH, SQUARE_HEIGHT)
|
|
return object
|
|
if self.type == 'R':
|
|
object = Rock(self.rect.center[0],self.rect.center[1],SQUARE_WIDTH, SQUARE_HEIGHT)
|
|
return object
|
|
if self.type == 'B':
|
|
object = Mine(self.rect.center[0],self.rect.center[1],SQUARE_WIDTH, SQUARE_HEIGHT)
|
|
return object
|
|
|
|
|
|
|
|
class Board:
|
|
fields = [] # tablica obiektów klasy filed, czyli po prostu tablica pól planszy gotowych do wizualizacji
|
|
bombs = 0
|
|
def __init__(self):
|
|
self.margin = MARGIN
|
|
self.square_high = SQUARE_HEIGHT
|
|
self.square_width = SQUARE_WIDTH
|
|
self.center_dist = CENTER_DIST
|
|
self.window_height = WINDOW_HEIGHT
|
|
self.window_widhth = WINDOW_WIDTH
|
|
self.boardcols = BOARDCOLS # liczba kolumn planszy
|
|
self.boardrows = BOARDROWS # liczba wierszy planszy
|
|
self.board = [[0 for i in range(self.boardcols)] for j in range(self.boardrows)]
|
|
self.firstwinner = True
|
|
|
|
pygame.display.set_caption("Saper")
|
|
self.game_display = pygame.display.set_mode((self.window_height, self.window_widhth)) # wielkość okna adaptująca się do wielkości planszy
|
|
self.load_board()
|
|
self.first_ground = self.board[0].index('T')
|
|
self.show_board()
|
|
self.init_board()
|
|
#self.bombfield = pathfinder.find_bomb(self.fields, self.first_ground)
|
|
self.genetic = pathfinder.Genetic(self.fields, self.first_ground)
|
|
self.bombfield = self.genetic.genetic_path.fields_order[0]
|
|
#print(self.bombfield)
|
|
self.pathf = pathfinder.Pathfind(self.fields, self.bombfield, self.first_ground)
|
|
self.ir = ImageRecognizer()
|
|
self.dt = DecisionTree()
|
|
|
|
def load_board(self): # funkcja tworząca tablicę opisującą planszę
|
|
for i in range(self.boardrows):
|
|
for j in range(self.boardcols):
|
|
chance = random.randint(1,100) # prawdopodobieństwo że dane pole będzie terenem (T), przeszkodą (O) lub bombą (B)
|
|
if chance >= 1 and chance < 80:
|
|
self.board[i][j] = 'T'
|
|
if chance >= 80 and chance < 95:
|
|
chance = random.randint(1,2)
|
|
if chance == 1:
|
|
self.board[i][j] = 'R'
|
|
if chance == 2:
|
|
self.board[i][j] = 'P'
|
|
|
|
if chance >= 95 and chance <= 100:
|
|
self.board[i][j] = 'B'
|
|
self.bombs += 1
|
|
|
|
def show_board(self): # funkcja pomocnicza wypisująca tablicę opisującą planszę
|
|
for i in range(self.boardrows):
|
|
for j in range(self.boardcols):
|
|
print(self.board[i][j], end=' ')
|
|
print("")
|
|
print("")
|
|
print("bomby:",self.bombs)
|
|
|
|
def init_board(self): # funkcja inicjująca planszę
|
|
x = self.margin
|
|
y = self.margin
|
|
for i in range(self.boardrows):
|
|
for j in range(self.boardcols):
|
|
if self.board[i][j] == 'T':
|
|
Field((x, y), (0, 128,0), 'T') # tworzony jest obiekt clasy field zawierający współżędne oraz kolor danego pola planszy
|
|
if self.board[i][j] == 'R':
|
|
Field((x, y), (255, 255, 0), 'R')
|
|
if self.board[i][j] == 'P':
|
|
Field((x, y), (255, 255, 0), 'P')
|
|
if self.board[i][j] == 'B':
|
|
Field((x, y), (165, 42, 42), 'B')
|
|
|
|
x += self.center_dist
|
|
y += self.center_dist
|
|
x = self.margin
|
|
|
|
def objects_display(self,i):
|
|
objecttype = self.fields[i].object
|
|
self.game_display.blit(objecttype.image_scaled, objecttype.rect)
|
|
|
|
def board_events(self, agent):
|
|
|
|
for event in pygame.event.get():
|
|
self.agent_field_update(agent)
|
|
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: # klawisz esc zamyka program
|
|
sys.exit(0)
|
|
|
|
#if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT and agent.pos_field+1 < len(self.fields):
|
|
# if self.fields[agent.pos_field+1].object.walkable == 0:
|
|
# self.fields[agent.pos_field].redisp = True
|
|
# agent.move(self.window_height, self.margin, self.center_dist, "RIGHT", 1)
|
|
|
|
#if event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT and agent.pos_field-1 >= 0:
|
|
# if self.fields[agent.pos_field - 1].object.walkable == 0:
|
|
# self.fields[agent.pos_field].redisp = True
|
|
# agent.move(self.window_height, self.margin, self.center_dist, "LEFT", -1)
|
|
|
|
#if event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN and agent.pos_field+BOARDROWS < len(self.fields):
|
|
# if self.fields[agent.pos_field + BOARDROWS].object.walkable == 0:
|
|
# self.fields[agent.pos_field].redisp = True
|
|
# agent.move(self.window_height, self.margin, self.center_dist, "DOWN", BOARDROWS)
|
|
|
|
#if event.type == pygame.KEYDOWN and event.key == pygame.K_UP and agent.pos_field-BOARDROWS >= 0:
|
|
# if self.fields[agent.pos_field - BOARDROWS].object.walkable == 0:
|
|
# self.fields[agent.pos_field].redisp = True
|
|
# agent.move(self.window_height,self.margin,self.center_dist,"UP", -BOARDROWS)
|
|
|
|
|
|
def agent_field_update(self,agent):
|
|
agent.cooldown = 100
|
|
if self.fields[agent.pos_field].type == 'B' and self.fields[agent.pos_field].object.defused == False:
|
|
if self.ir.recognize(self.fields[agent.pos_field].object.itr) == "stones":
|
|
print("to kamień!")
|
|
self.fields[agent.pos_field].object.its_rock(SQUARE_WIDTH, SQUARE_HEIGHT)
|
|
self.fields[agent.pos_field].redisp = True
|
|
self.bombs -= 1
|
|
else:
|
|
print("to bomba!")
|
|
wtd = self.dt.make_decision(((self.bombs*100)//(BOARDCOLS**2))+1, self.fields[agent.pos_field].object.time, self.fields[agent.pos_field].object.reach)
|
|
if wtd == "Defuse":
|
|
self.fields[agent.pos_field].object.defuse(SQUARE_WIDTH, SQUARE_HEIGHT)
|
|
self.fields[agent.pos_field].redisp = True
|
|
if wtd == "Move away":
|
|
self.fields[agent.pos_field].object.move_away(SQUARE_WIDTH, SQUARE_HEIGHT)
|
|
self.fields[agent.pos_field].redisp = True
|
|
self.bombs -= 1
|
|
if self.bombs > 0 and agent.pos_field == self.bombfield:
|
|
#self.bombfield = pathfinder.find_bomb(self.fields, agent.pos_field)
|
|
#print(self.bombfield)
|
|
self.genetic.genetic_path.fields_order.remove(self.genetic.genetic_path.fields_order[0])
|
|
self.bombfield = self.genetic.genetic_path.fields_order[0]
|
|
print("next bombfield is: ", self.bombfield)
|
|
self.pathf = pathfinder.Pathfind(self.fields, self.bombfield, agent.pos_field)
|
|
|
|
|
|
|
|
def automove_agent(self,agent):
|
|
self.agent_field_update(agent)
|
|
if len(self.pathf.way) > 0:
|
|
wayfield = self.pathf.way[0]
|
|
self.pathf.way.remove(wayfield)
|
|
if agent.pos_field - BOARDCOLS == wayfield:
|
|
self.fields[agent.pos_field].redisp = True
|
|
agent.move(self.window_height, self.margin, self.center_dist, "UP", -BOARDCOLS)
|
|
|
|
if agent.pos_field + BOARDCOLS == wayfield:
|
|
self.fields[agent.pos_field].redisp = True
|
|
agent.move(self.window_height, self.margin, self.center_dist, "DOWN", BOARDCOLS)
|
|
|
|
if agent.pos_field - 1 == wayfield:
|
|
self.fields[agent.pos_field].redisp = True
|
|
agent.move(self.window_height, self.margin, self.center_dist, "LEFT", -1)
|
|
|
|
if agent.pos_field + 1 == wayfield:
|
|
self.fields[agent.pos_field].redisp = True
|
|
agent.move(self.window_height, self.margin, self.center_dist, "RIGHT", 1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def full_board_display(self,first): # funkcja pomocnicza wywołująca program, w celu wizualizacji planszy możną ją wywołać
|
|
if self.bombs <= 0 and self.firstwinner == True:
|
|
print("wszystkie miny rozbrojone!")
|
|
self.firstwinner = False
|
|
|
|
if first == True:
|
|
self.game_display.fill((0, 0, 0))
|
|
i=0
|
|
for square in self.fields:
|
|
if square.redisp == True:
|
|
pygame.draw.rect(self.game_display, square.color, square.rect)
|
|
self.objects_display(i)
|
|
square.redisp = False
|
|
i=i+1 |