Untitled

 avatar
unknown
plain_text
4 years ago
32 kB
5
Indexable
import time
import copy
import pygame
import queue
import sys


ADANCIME_MAX = 1
GAME_LINES = 9
GAME_COLUMNS = 9
INITIAL_WALLS = 10
WALL_LINE_WIDTH = 10


def elem_identice(lista):
    if(len(set(lista)) == 1):
        return lista[0] if lista[0] != Joc.GOL else False
    return False


class RectPosition:

    W_RECT = None
    W_BAR = None

    def __init__(self, lin=None, col=None, grid_pos=None):
        if grid_pos is None:
            self.lin = lin
            self.col = col
        else:
            size = self.__class__.W_RECT + self.__class__.W_BAR
            self.lin = grid_pos[1] // size
            self.col = grid_pos[0] // size

    @classmethod
    def initialize(cls, w_bars, w_rect):
        RectPosition.W_BAR = w_bars
        RectPosition.W_RECT = w_rect

    def get_grid_postition(self):
        size = self.__class__.W_RECT + self.__class__.W_BAR

        return (self.col * size + self.__class__.W_BAR, self.lin * size + self.__class__.W_BAR)

    def __eq__(self, other):
        return self.lin == other.lib and self.col == other.col


class BarPosition:
    W_RECT = None
    W_BAR = None

    def __init__(self, lin=None, col=None, is_horiz=None, grid_pos=None):
        if grid_pos is None:
            self.lin = lin
            self.col = col
            self.is_horiz = is_horiz
        else:
            size = self.__class__.W_RECT + self.__class__.W_BAR
            self.lin = grid_pos[1] // size
            self.col = grid_pos[0] // size
            self.is_horiz = grid_pos[0] % size >= self.__class__.W_BAR

    @classmethod
    def initialize(cls, w_bars, w_rect):
        BarPosition.W_BAR = w_bars
        BarPosition.W_RECT = w_rect

    '''
    given a position of the same type, say if there's a bar there or not
    (don't take into account )
    '''

    def __eq__(self, other):
        if other.is_horiz != self.is_horiz:
            return False

        if self.lin == other.lin and self.col == other.col:
            return True

        if self.is_horiz == True and self.lin == other.lin and self.col - 1 == other.col:
            return True

        if self.is_horiz == False and self.lin - 1 == other.lin and self.col == other.col:
            return True

        return False

    def __str__(self):
        return "{} {}".format(self.lin, self.col)

    def does_not_collide(self, other_wall):
        if other_wall.is_horiz:
            if self.is_horiz:
                return (self.col > (other_wall.col + 1)) or ((self.col + 1) < other_wall.col) or other_wall.lin != self.lin
            else:
                return (self.lin + 1 != other_wall.lin) or (self.col != (other_wall.col + 1))
        else:
            if self.is_horiz:
                return (self.col + 1 != other_wall.col) or (other_wall.lin + 1 != self.lin)
            else:
                return other_wall.col != self.col or self.lin > other_wall.lin or self.lin + 1 < other_wall.lin


class Joc:
    """
    Clasa care defineste jocul. Se va schimba de la un joc la altul.
    """
    JMIN = None
    JMAX = None
    GOL = '#'
    NR_LINII = None
    NR_COLOANE = None
    scor_maxim = 999

    def __init__(self, other_game=None, NR_LINII=None, NR_COLOANE=None):
        # creez proprietatea ultima_mutare # (l,c)
        self.ultima_mutare = None

        if other_game:
            # e data tabla, deci suntem in timpul jocului
            self.matr = copy.deepcopy(other_game.matr)
            self.blue = copy.deepcopy(other_game.blue)
            self.red = copy.deepcopy(other_game.red)
            self.walls = copy.deepcopy(other_game.walls)
            self.no_walls = copy.deepcopy(other_game.no_walls)

        else:
            # nu e data tabla deci suntem la initializare
            self.matr = [[self.__class__.GOL] *
                         NR_COLOANE for i in range(NR_LINII)]

            # initializez jucatorii
            self.blue = RectPosition(0, NR_COLOANE // 2)
            self.red = RectPosition(NR_LINII - 1, NR_COLOANE // 2)

            self.matr[self.blue.lin][self.blue.col] = 'b'
            self.matr[self.red.lin][self.red.col] = 'r'

            if NR_LINII is not None:
                self.__class__.NR_LINII = NR_LINII
            if NR_COLOANE is not None:
                self.__class__.NR_COLOANE = NR_COLOANE

            self.no_walls = {}
            self.no_walls['r'] = INITIAL_WALLS
            self.no_walls['b'] = INITIAL_WALLS
            self.walls = []

            # ######## calculare scor maxim ###########
            # sc_randuri = (NR_COLOANE-3)*NR_LINII
            # sc_coloane = (NR_LINII - 3)*NR_COLOANE
            # sc_diagonale = (NR_LINII - 3) * (NR_COLOANE - 3) * 2
            # self.__class__.scor_maxim = sc_randuri + sc_coloane + sc_diagonale

    # tabla de exemplu este ["#","x","#","0",......]
    def deseneaza_grid(self, coloana_marcaj=None):
        for ind in range(self.__class__.NR_COLOANE*self.__class__.NR_LINII):
            linie = ind // self.__class__.NR_COLOANE  # // inseamna div
            coloana = ind % self.__class__.NR_COLOANE

            if coloana == coloana_marcaj:
                # daca am o patratica selectata, o desenez cu rosu
                culoare = (255, 255, 0)
            else:
                # altfel o desenez cu alb
                culoare = (255, 255, 255)
            pygame.draw.rect(self.__class__.display, culoare,
                             self.__class__.celuleGrid[ind])  # alb = (255,255,255)
            if self.red.lin == linie and self.red.col == coloana:
                self.__class__.display.blit(
                    self.__class__.red_img, self.red.get_grid_postition())
            elif self.blue.lin == linie and self.blue.col == coloana:
                self.__class__.display.blit(
                    self.__class__.blue_img, self.blue.get_grid_postition())
        # pygame.display.flip()
        for bar_pos in self.walls:
            culoare = (50, 205, 50)

            if bar_pos.is_horiz == True:
                bar = pygame.Rect(
                    bar_pos.col * (self.dim_bar + self.dim_celula) + self.dim_bar, bar_pos.lin * (self.dim_bar + self.dim_celula), 2 * self.dim_celula + self.dim_bar, self.dim_bar)
                self.bars.append(bar)
            else:
                bar = pygame.Rect(
                    bar_pos.col * (self.dim_bar + self.dim_celula), bar_pos.lin * (self.dim_bar + self.dim_celula) + self.dim_bar, self.dim_bar,  2 * self.dim_celula + self.dim_bar)
                self.bars.append(bar)

            pygame.draw.rect(self.__class__.display, culoare, bar)

        pygame.display.update()

    def can_place_wall(self, bar_pos, j_curent):
        # TODO: check if placing a wall here does not block the game

        if self.bfs('r', [bar_pos]) == -1 or self.bfs('b', [bar_pos]) == -1:
            return False

        not_collide = True
        for wall in self.walls:
            if not bar_pos.does_not_collide(wall):
                not_collide = False
        # print("Can place bar ", not_collide and self.no_walls[j_curent] > 0)
        # am scos verificarea deoarece lua mult
        return not_collide and self.no_walls[j_curent] > 0
        # return not_collide and self.no_walls[j_curent] > 0

    def place_wall(self, bar_pos, j_curent):
        self.no_walls[j_curent] -= 1
        self.walls.append(bar_pos)

        # if bar_pos.is_horiz == True:
        #     bar = pygame.Rect(
        #         bar_pos.col * (self.dim_bar + self.dim_celula) + self.dim_bar, bar_pos.lin * (self.dim_bar + self.dim_celula), 2 * self.dim_celula + self.dim_bar, self.dim_bar)
        #     self.bars.append(bar)
        # else:
        #     bar = pygame.Rect(
        #         bar_pos.col * (self.dim_bar + self.dim_celula), bar_pos.lin * (self.dim_bar + self.dim_celula) + self.dim_bar, self.dim_bar,  2 * self.dim_celula + self.dim_bar)
        #     self.bars.append(bar)

    # calculate minimal number of steps to the target
    def bfs(self, player, extra_walls=[], get_min=False):
        # print("HERE?", player)
        initial_pos, target_lin = (self.red, 0) if player == 'r' else (
            self.blue, self.NR_LINII - 1)
        q = queue.Queue()

        lins = [0, 0, -1, 1]
        cols = [1, -1, 0, 0]

        visited = [[False for _ in range(self.NR_COLOANE)]
                   for _ in range(self.NR_LINII)]
        q.put((initial_pos, 0))
        min_dis = float('inf')
        while not q.empty():
            p, dist = q.get()
            if visited[p.lin][p.col] == True:
                continue
            visited[p.lin][p.col] = True

            if p.lin == target_lin:
                if not get_min:
                    return 1
                min_dis = min(min_dis, dist)

            for i in range(4):
                l = lins[i]
                c = cols[i]
                next_pos = RectPosition(lin=p.lin + l, col=p.col + c)

                if self.can_pawn_advance(p, next_pos, extra_walls) and not visited[next_pos.lin][next_pos.col]:
                    q.put((next_pos, dist + 1))

        if min_dis == float('inf'):
            return -1
        return min_dis

    def can_pawn_advance(self, current_pos, new_pos, extra_walls=[]):
        if new_pos.lin < 0 or new_pos.col < 0 or new_pos.lin >= self.NR_LINII or new_pos.col >= self.NR_COLOANE:
            return False

        if new_pos.col == current_pos.col and new_pos.lin == current_pos.lin - 1:

            # check if there's a another bar by observing if we could place a wall between
            # these 2
            bar = BarPosition(current_pos.lin, current_pos.col, True)
            if not bar in (self.walls + extra_walls):
                return True
            return False

        elif new_pos.col == current_pos.col and new_pos.lin == current_pos.lin + 1:
            bar = BarPosition(new_pos.lin, new_pos.col, True)

            if not bar in (self.walls + extra_walls):
                return True
            return False

        elif new_pos.col == current_pos.col + 1 and new_pos.lin == current_pos.lin:
            bar = BarPosition(new_pos.lin, new_pos.col, False)

            if not bar in (self.walls + extra_walls):
                return True
            return False

        elif new_pos.col == current_pos.col - 1 and new_pos.lin == current_pos.lin:
            bar = BarPosition(current_pos.lin, current_pos.col, False)

            if not bar in (self.walls + extra_walls):
                return True
            return False
        return False

    def is_new_pawn_position_valid(self, jucator, new_pos, extra_walls=[]):
        current_pos = self.red if jucator == 'r' else self.blue

        return self.can_pawn_advance(current_pos, new_pos, extra_walls)

    def move_pawn(self, jucator, new_pos):
        current_pos = self.red if jucator == 'r' else self.blue

        self.matr[current_pos.lin][current_pos.col] = self.__class__.GOL
        if jucator == 'r':
            self.red = new_pos
        else:
            self.blue = new_pos

        self.matr[new_pos.lin][new_pos.col] = jucator

    @classmethod
    def jucator_opus(cls, jucator):
        return cls.JMAX if jucator == cls.JMIN else cls.JMIN

    @classmethod
    def initializeaza(cls, display, NR_LINII=GAME_LINES, NR_COLOANE=GAME_COLUMNS, dim_celula=100, dim_bar=0):
        cls.display = display
        cls.dim_celula = dim_celula
        cls.dim_bar = dim_bar
        cls.red_img = pygame.image.load('red.png')
        cls.red_img = pygame.transform.scale(
            cls.red_img, (dim_celula, dim_celula))
        cls.blue_img = pygame.image.load('blue.png')
        cls.blue_img = pygame.transform.scale(
            cls.blue_img, (dim_celula, dim_celula))
        cls.celuleGrid = []  # este lista cu patratelele din grid
        cls.bars = []  # list cu locurile pentru pereti
        RectPosition.initialize(dim_bar, dim_celula)
        BarPosition.initialize(dim_bar, dim_celula)

        for linie in range(NR_LINII):
            for coloana in range(NR_COLOANE):
                patr = pygame.Rect(coloana*(dim_celula) + (coloana + 1) * dim_bar,
                                   linie*(dim_celula) + (linie + 1) * dim_bar, dim_celula, dim_celula)
                cls.celuleGrid.append(patr)

    def parcurgere(self, directie):
        um = self.ultima_mutare  # (l,c)
        culoare = self.matr[um[0]][um[1]]
        nr_mutari = 0
        while True:
            um = (um[0] + directie[0], um[1] + directie[1])
            if not 0 <= um[0] < self.__class__.NR_LINII or not 0 <= um[1] < self.__class__.NR_COLOANE:
                break
            if not self.matr[um[0]][um[1]] == culoare:
                break
            nr_mutari += 1
        return nr_mutari

    def final(self):
        if self.blue.lin == self.NR_LINII - 1:
            return 'b'
        if self.red.lin == 0:
            return 'r'
        return False

    def mutari(self, jucator):
        l_mutari = []

        stats = TimeStats()

        current_pos = self.red if jucator == 'r' else self.blue
        next_lins = [0, 0, 1, -1]
        next_cols = [1, -1, 0, 0]

        for i in range(4):
            next_pos = copy.deepcopy(current_pos)
            next_pos.lin += next_lins[i]
            next_pos.col += next_cols[i]

            if self.is_new_pawn_position_valid(jucator, next_pos):
                new_game = Joc(self)
                new_game.move_pawn(jucator, next_pos)
                l_mutari.append(new_game)

        # try to place bars
        # for i in range(self.NR_LINII - 1):
        #     for j in range(self.NR_COLOANE - 1):
        #         horiz_bar = BarPosition(i, j, True)
        #         stats.start_timer()

        #         if self.can_place_wall(horiz_bar, jucator):
        #             new_game = Joc(self)
        #             new_game.place_wall(horiz_bar, jucator)
        #             l_mutari.append(new_game)

        #         horiz_bar = BarPosition(i, j, False)

        #         if self.can_place_wall(horiz_bar, jucator):
        #             new_game = Joc(self)
        #             new_game.place_wall(horiz_bar, jucator)
        #             l_mutari.append(new_game)
                # print("2 mutari", len(l_mutari), stats.stop_timer())

        # print("NO MUTARI", len(l_mutari), stats2.stop_timer())
        return l_mutari

    # linie deschisa inseamna linie pe care jucatorul mai poate forma o configuratie castigatoare
    # practic e o linie fara simboluri ale jucatorului opus
    def linie_deschisa(self, lista, jucator):
        jo = self.jucator_opus(jucator)
        # verific daca pe linia data nu am simbolul jucatorului opus
        if not jo in lista:
            # return 1
            return lista.count(jucator)
        return 0

    def estimeaza_scor(self, adancime):
        t_final = self.final()
        # if (adancime==0):
        if t_final == self.__class__.JMAX:
            return (self.__class__.scor_maxim+adancime)
        elif t_final == self.__class__.JMIN:
            return (-self.__class__.scor_maxim-adancime)
        else:
            print("STARE SI SCOR")
            print(self)
            print(self.bfs(self.__class__.JMAX, get_min=True), self.bfs(
                self.__class__.JMIN, get_min=True), self.__class__.JMAX, self.__class__.JMIN)
            return self.bfs(self.__class__.JMAX, get_min=True) - self.bfs(self.__class__.JMIN, get_min=True)

    def sirAfisare(self):
        sir = "  |"
        sir += " ".join([str(i) for i in range(self.NR_COLOANE)])+"\n"
        sir += "-"*(self.NR_COLOANE+1)*2+"\n"
        # sir += "\n".join([str(i)+" |"+" ".join([str(x)
        #                  for x in self.matr[i]]) for i in range(len(self.matr))])

        for i in range(self.NR_LINII):
            sir += str(i) + " |"
            # horizontal bars
            for j in range(self.NR_COLOANE):
                if BarPosition(i, j, True) in self.walls:
                    sir += ' -'
                else:
                    sir += '  '

            sir += '\n'
            sir += '  |'

            for j in range(self.NR_COLOANE):
                if BarPosition(i, j, False) in self.walls:
                    sir += '|'
                else:
                    sir += ' '

                sir += self.matr[i][j]

            sir += '\n'

        return sir

    def __str__(self):
        return self.sirAfisare()

    def __repr__(self):
        return self.sirAfisare()


class Stare:
    """
    Clasa folosita de algoritmii minimax si alpha-beta
    Are ca proprietate tabla de joc
    Functioneaza cu conditia ca in cadrul clasei Joc sa fie definiti JMIN si JMAX (cei doi jucatori posibili)
    De asemenea cere ca in clasa Joc sa fie definita si o metoda numita mutari() care ofera lista cu configuratiile posibile in urma mutarii unui jucator
    """

    def __init__(self, tabla_joc, j_curent, adancime, parinte=None, scor=None):
        self.tabla_joc = tabla_joc
        self.j_curent = j_curent

        # adancimea in arborele de stari
        self.adancime = adancime

        # scorul starii (daca e finala) sau al celei mai bune stari-fiice (pentru jucatorul curent)
        self.scor = scor

        # lista de mutari posibile din starea curenta
        self.mutari_posibile = []

        # cea mai buna mutare din lista de mutari posibile pentru jucatorul curent
        self.stare_aleasa = None

    def mutari(self):
        l_mutari = self.tabla_joc.mutari(self.j_curent)
        # print("NO NEXT MOVES", len(l_mutari))
        juc_opus = Joc.jucator_opus(self.j_curent)
        l_stari_mutari = [
            Stare(mutare, juc_opus, self.adancime-1, parinte=self) for mutare in l_mutari]

        return l_stari_mutari

    def __str__(self):
        sir = str(self.tabla_joc) + "(Juc curent:"+self.j_curent+")\n"
        return sir

    def __repr__(self):
        sir = str(self.tabla_joc) + "(Juc curent:"+self.j_curent+")\n"
        return sir


""" Algoritmul MinMax """


class TimeStats:
    def __init__(self):
        self.start = None
        self.history = []

    def start_timer(self):
        if self.start == None:
            self.start = int(round(time.time() * 1000))

    def stop_timer(self):
        current = int(round(time.time() * 1000))
        total_time = current - self.start
        self.history.append(total_time)
        self.start = None

        return total_time

    def get_min(self):
        return min(self.history)

    def get_max(self):
        return max(self.history)

    def get_avg(self):
        return sum(self.history) / len(self.history)

    def get_median(self):
        return statistics.median(self.history)

    def __str__(self):
        return "Min:{}\nMax: {}\nAverage: {}\nMedian: {}\n".format(
            self.get_min(), self.get_max(), self.get_avg(), self.get_median()
        )


def min_max(stare):
    # print("WHAT!??!?!?!")
    # print(stare.adancime)
    # print(str(stare.tabla_joc))
    st = TimeStats()
    st.start_timer()
    if stare.adancime == 0 or stare.tabla_joc.final():
        stare.scor = stare.tabla_joc.estimeaza_scor(stare.adancime)
        return stare
    # calculez toate mutarile posibile din starea curenta
    stare.mutari_posibile = stare.mutari()
    print("NOT LA FINAL", len(stare.mutari_posibile),    st.stop_timer())

    # aplic algoritmul minimax pe toate mutarile posibile (calculand astfel subarborii lor)
    mutari_scor = [min_max(mutare) for mutare in stare.mutari_posibile]

    if stare.j_curent == Joc.JMAX:
        # daca jucatorul e JMAX aleg starea-fiica cu scorul maxim
        stare.stare_aleasa = max(mutari_scor, key=lambda x: x.scor)
    else:
        # daca jucatorul e JMIN aleg starea-fiica cu scorul minim
        stare.stare_aleasa = min(mutari_scor, key=lambda x: x.scor)
    stare.scor = stare.stare_aleasa.scor
    return stare


def alpha_beta(alpha, beta, stare):
    if stare.adancime == 0 or stare.tabla_joc.final():
        stare.scor = stare.tabla_joc.estimeaza_scor(stare.adancime)
        return stare

    if alpha > beta:
        return stare  # este intr-un interval invalid deci nu o mai procesez

    stare.mutari_posibile = stare.mutari()

    if stare.j_curent == Joc.JMAX:
        scor_curent = float('-inf')

        for mutare in stare.mutari_posibile:
            # calculeaza scorul
            stare_noua = alpha_beta(alpha, beta, mutare)

            if (scor_curent < stare_noua.scor):
                stare.stare_aleasa = stare_noua
                scor_curent = stare_noua.scor
            if(alpha < stare_noua.scor):
                alpha = stare_noua.scor
                if alpha >= beta:
                    break

    elif stare.j_curent == Joc.JMIN:
        scor_curent = float('inf')

        for mutare in stare.mutari_posibile:

            stare_noua = alpha_beta(alpha, beta, mutare)

            if (scor_curent > stare_noua.scor):
                stare.stare_aleasa = stare_noua
                scor_curent = stare_noua.scor

            if(beta > stare_noua.scor):
                beta = stare_noua.scor
                if alpha >= beta:
                    break
    stare.scor = stare.stare_aleasa.scor

    return stare


def afis_daca_final(stare_curenta):
    final = stare_curenta.tabla_joc.final()
    # print("FIANL IS", final)
    if(final):
        if (final == "remiza"):
            print("Remiza!")
        else:
            print("A castigat "+final)

        return True

    return False


class Buton:
    def __init__(self, display=None, left=0, top=0, w=0, h=0, culoareFundal=(53, 80, 115), culoareFundalSel=(89, 134, 194), text="", font="arial", fontDimensiune=16, culoareText=(255, 255, 255), valoare=""):
        self.display = display
        self.culoareFundal = culoareFundal
        self.culoareFundalSel = culoareFundalSel
        self.text = text
        self.font = font
        self.w = w
        self.h = h
        self.selectat = False
        self.fontDimensiune = fontDimensiune
        self.culoareText = culoareText
        # creez obiectul font
        fontObj = pygame.font.SysFont(self.font, self.fontDimensiune)
        self.textRandat = fontObj.render(self.text, True, self.culoareText)
        self.dreptunghi = pygame.Rect(left, top, w, h)
        # aici centram textul
        self.dreptunghiText = self.textRandat.get_rect(
            center=self.dreptunghi.center)
        self.valoare = valoare

    def selecteaza(self, sel):
        self.selectat = sel
        self.deseneaza()

    def selecteazaDupacoord(self, coord):
        if self.dreptunghi.collidepoint(coord):
            self.selecteaza(True)
            return True
        return False

    def updateDreptunghi(self):
        self.dreptunghi.left = self.left
        self.dreptunghi.top = self.top
        self.dreptunghiText = self.textRandat.get_rect(
            center=self.dreptunghi.center)

    def deseneaza(self):
        culoareF = self.culoareFundalSel if self.selectat else self.culoareFundal
        pygame.draw.rect(self.display, culoareF, self.dreptunghi)
        self.display.blit(self.textRandat, self.dreptunghiText)


class GrupButoane:
    def __init__(self, listaButoane=[], indiceSelectat=0, spatiuButoane=10, left=0, top=0):
        self.listaButoane = listaButoane
        self.indiceSelectat = indiceSelectat
        self.listaButoane[self.indiceSelectat].selectat = True
        self.top = top
        self.left = left
        leftCurent = self.left
        for b in self.listaButoane:
            b.top = self.top
            b.left = leftCurent
            b.updateDreptunghi()
            leftCurent += (spatiuButoane+b.w)

    def selecteazaDupacoord(self, coord):
        for ib, b in enumerate(self.listaButoane):
            if b.selecteazaDupacoord(coord):
                self.listaButoane[self.indiceSelectat].selecteaza(False)
                self.indiceSelectat = ib
                return True
        return False

    def deseneaza(self):
        # atentie, nu face wrap
        for b in self.listaButoane:
            b.deseneaza()

    def getValoare(self):
        return self.listaButoane[self.indiceSelectat].valoare


############# ecran initial ########################
def deseneaza_alegeri(display, tabla_curenta):
    btn_alg = GrupButoane(
        top=30,
        left=30,
        listaButoane=[
            Buton(display=display, w=80, h=30,
                  text="minimax", valoare="minimax"),
            Buton(display=display, w=80, h=30,
                  text="alphabeta", valoare="alphabeta")
        ],
        indiceSelectat=1)
    btn_juc = GrupButoane(
        top=100,
        left=30,
        listaButoane=[
            Buton(display=display, w=35, h=30, text="red", valoare="r"),
            Buton(display=display, w=35, h=30, text="blue", valoare="b")
        ],
        indiceSelectat=0)
    ok = Buton(display=display, top=170, left=30, w=40,
               h=30, text="ok", culoareFundal=(155, 0, 55))
    btn_alg.deseneaza()
    btn_juc.deseneaza()
    ok.deseneaza()
    while True:
        for ev in pygame.event.get():
            if ev.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif ev.type == pygame.MOUSEBUTTONDOWN:
                pos = pygame.mouse.get_pos()
                if not btn_alg.selecteazaDupacoord(pos):
                    if not btn_juc.selecteazaDupacoord(pos):
                        if ok.selecteazaDupacoord(pos):
                            display.fill((0, 0, 0))  # stergere ecran
                            tabla_curenta.deseneaza_grid()
                            return btn_juc.getValoare(), btn_alg.getValoare()
        pygame.display.update()


def main():
    # setari interf grafica
    pygame.init()
    pygame.display.set_caption("Enache Adelina: Quoridor")
    # dimensiunea ferestrei in pixeli
    nl = GAME_LINES
    nc = GAME_COLUMNS
    w_rect = 50
    w_bars = 15

    ecran = pygame.display.set_mode(
        size=(nc*w_rect + (w_bars + 1) * nc, nl*w_rect + (w_bars + 1) * nl))  # N *w+ N-1= N*(w+1)-1
    Joc.initializeaza(ecran, NR_LINII=nl, NR_COLOANE=nc,
                      dim_celula=w_rect, dim_bar=w_bars)

    # initializare tabla
    tabla_curenta = Joc(NR_LINII=nl, NR_COLOANE=nc)
    Joc.JMIN, tip_algoritm = deseneaza_alegeri(ecran, tabla_curenta)
    print(Joc.JMIN, tip_algoritm)

    Joc.JMAX = 'b' if Joc.JMIN == 'r' else 'r'

    print("Tabla initiala")
    print(str(tabla_curenta))

    # creare stare initiala
    stare_curenta = Stare(tabla_curenta, 'r', ADANCIME_MAX)
    print(stare_curenta.j_curent, Joc.JMIN)
    tabla_curenta.deseneaza_grid()
    while True:

        if (stare_curenta.j_curent == Joc.JMIN):

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    # iesim din program
                    pygame.quit()
                    sys.exit()
                if event.type == pygame.MOUSEMOTION:

                    pos = pygame.mouse.get_pos()  # coordonatele cursorului
                    for np in range(len(Joc.celuleGrid)):
                        if Joc.celuleGrid[np].collidepoint(pos):

                            stare_curenta.tabla_joc.deseneaza_grid(
                                coloana_marcaj=np % Joc.NR_COLOANE)
                            break

                elif event.type == pygame.MOUSEBUTTONDOWN:

                    clicked_on_square = False

                    pos = pygame.mouse.get_pos()  # coordonatele cursorului la momentul clickului

                    for np in range(len(Joc.celuleGrid)):

                        if Joc.celuleGrid[np].collidepoint(pos):
                            clicked_on_square = True
                            print("Clicked on square")
                            # linie = np//Joc.NR_COLOANE
                            # coloana = np % Joc.NR_COLOANE

                            square_pos = RectPosition(grid_pos=pos)
                            ###############################

                            print("Square position is:",
                                  square_pos.lin, " ", square_pos.col)

                            print(stare_curenta.tabla_joc.is_new_pawn_position_valid(
                                Joc.JMAX, square_pos))

                            if stare_curenta.tabla_joc.is_new_pawn_position_valid(Joc.JMIN, square_pos):
                                print("OK GOOD POS")
                                stare_curenta.tabla_joc.move_pawn(
                                    Joc.JMIN, square_pos)

                                # niv = 0
                                # while True:
                                #     if niv == Joc.NR_LINII or stare_curenta.tabla_joc.matr[niv][coloana] != Joc.GOL:
                                #         stare_curenta.tabla_joc.matr[niv -
                                #                                      1][coloana] = Joc.JMIN
                                #         stare_curenta.tabla_joc.ultima_mutare = (
                                #             niv-1, coloana)
                                #         break
                                #     niv += 1

                                # afisarea starii jocului in urma mutarii utilizatorului
                                print("\nTabla dupa mutarea jucatorului")
                                print(str(stare_curenta))

                                stare_curenta.tabla_joc.deseneaza_grid()
                                # testez daca jocul a ajuns intr-o stare finala
                                # si afisez un mesaj corespunzator in caz ca da
                                if (afis_daca_final(stare_curenta)):
                                    break

                                # S-a realizat o mutare. Schimb jucatorul cu cel opus
                                stare_curenta.j_curent = Joc.jucator_opus(
                                    stare_curenta.j_curent)

                    if not clicked_on_square:
                        # print("CLICKED ON BAR", pos)
                        bar_pos = BarPosition(grid_pos=pos)
                        # print(bar_pos.lin, bar_pos.col, bar_pos.is_horiz)

                        if stare_curenta.tabla_joc.can_place_wall(bar_pos, stare_curenta.j_curent):
                            stare_curenta.tabla_joc.place_wall(
                                bar_pos, stare_curenta.j_curent)

                            print("\nTabla dupa mutarea jucatorului")
                            print(str(stare_curenta))

                            stare_curenta.tabla_joc.deseneaza_grid()
                            # testez daca jocul a ajuns intr-o stare finala
                            # si afisez un mesaj corespunzator in caz ca da
                            if (afis_daca_final(stare_curenta)):
                                break

                            # S-a realizat o mutare. Schimb jucatorul cu cel opus
                            stare_curenta.j_curent = Joc.jucator_opus(
                                stare_curenta.j_curent)

        # --------------------------------
        else:  # jucatorul e JMAX (calculatorul)
            # Mutare calculator
            pass
            # time.sleep(100000)
            # preiau timpul in milisecunde de dinainte de mutare
            t_inainte = int(round(time.time() * 1000))
            if tip_algoritm == 'minimax':
                stare_actualizata = min_max(stare_curenta)
                # print("NEW STARE RERERERERERE")
            else:  # tip_algoritm=="alphabeta"
                stare_actualizata = alpha_beta(-500, 500, stare_curenta)
            stare_curenta.tabla_joc = stare_actualizata.stare_aleasa.tabla_joc

            print("Tabla dupa mutarea calculatorului\n"+str(stare_curenta))

            # preiau timpul in milisecunde de dupa mutare
            t_dupa = int(round(time.time() * 1000))
            print("Calculatorul a \"gandit\" timp de " +
                  str(t_dupa-t_inainte)+" milisecunde.")

            stare_curenta.tabla_joc.deseneaza_grid()
            if (afis_daca_final(stare_curenta)):
                break

            # S-a realizat o mutare. Schimb jucatorul cu cel opus
            stare_curenta.j_curent = Joc.jucator_opus(stare_curenta.j_curent)


if __name__ == "__main__":
    main()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
Editor is loading...