Ejemplo n.º 1
0
def MiniMaxValue(board, node, isMax):
    """
    Gets the made tree top node and going through it recursively
    to min or max over children

    board -> Getting the current board
    node -> top node of created miniMax tree 
    isMax -> Is this iteration of recursive for maxing over children or mining
    """
    """
    MinimaxValue: Going from top to bottom of the tree and min and maxing over
    nodes considering isMax variable and returning the min or max node in each parent.
    In the end the nominated node returns with its evaluation function point.
    """

    # If this node has no children
    if (len(node.GetChildren()) == 0):
        # Making a copy of the board
        currentBoard = Entities.Board()
        currentBoard.Copy(board)
        currentActions = node.actions.copy()

        # Looping over all actions in this node and updating the board
        for i in range(currentActions.__len__()):
            action = currentActions.popleft()
            currentBoard.Action(action[0], action[1])

        # Calculating the evaluation Function point
        node.point = currentBoard.EvaluationFunction()

        # returning this node
        return node

    # if this node has children
    else:
        # Recurse to children
        subNodes = []
        for child in node.GetChildren():
            subNodes.append(MiniMaxValue(board, child, not isMax))

        # If its the max turn, max over children nodes and return the max
        if (isMax):
            maxNode = max(subNodes, key=lambda x: x.point)
            node.point = maxNode.point
            return maxNode
        # If its the min turn, min over children nodes and return the min
        else:
            minNode = min(subNodes, key=lambda x: x.point)
            node.point = minNode.point
            return minNode
Ejemplo n.º 2
0
 def get_current_board(self):
     minions = []
     weapons = []
     heroes = []
     for board_card in self.game.in_zone(1):
         if type(board_card) == Card:
             id = board_card.card_id
             if id:
                 card_info = self.get_card_info(id)
                 card_type = card_info['type']
                 if card_info and card_type != "HERO_POWER":
                     tags = board_card.tags
                     if card_type == 'WEAPON':
                         weapon = entities.BoardWeapon(
                             card_info['name'], 
                             id, 
                             tags.get(GameTag.ZONE_POSITION, 0), 
                             board_card.controller, 
                             tags.get(GameTag.ATK, 0), 
                             tags.get(GameTag.DURABILITY, 0))
                         weapons.append(weapon)
                     elif card_type == 'MINION':
                         exhaust = tags.get(GameTag.EXHAUSTED, not tags.get(GameTag.CHARGE, 0))
                         if tags.get(GameTag.FROZEN):
                             exhaust = 1
                         minion = entities.BoardMinion(
                             card_info['name'], 
                             id, 
                             tags[GameTag.ZONE_POSITION], 
                             board_card.controller, 
                             tags.get(GameTag.ATK, 0), 
                             tags.get(GameTag.HEALTH, 0), 
                             tags.get(GameTag.TAUNT, 0), 
                             exhaust)
                         minions.append(minion)
                     elif card_type == 'HERO':
                         hero = entities.BoardHero(
                             card_info['name'],
                             id,
                             None,
                             board_card.controller,
                             tags.get(GameTag.HEALTH, 30) - tags.get(GameTag.DAMAGE, 0),
                             tags.get(GameTag.EXHAUSTED, 0)
                         )
                         heroes.append(hero)
     return entities.Board(minions, heroes, weapons)
Ejemplo n.º 3
0
def Reset():
    """
    Refresh the whole window for other experiments, it also 
    terminate the current thread of the gameplay, in the other hand,
    terminate the current running game.
    """
    global Display
    global Gameplay
    global Board
    global GameplayThread
    if (Gameplay != None):
        if (Gameplay.isGameTerminated == False):
            Gameplay.End()
        Gameplay = None

    Board = Entities.Board()
    Initialization()
Ejemplo n.º 4
0
A project at the university of Ashrafi Esfahani.
"""

import entities as Entities
import graphics as Graphics
import bot as Bot
import profiler as Profiler
import statistics as Statistics
import game as Game
import player as Player
import threading as Threading
import statistics

# Global instances
Display = Graphics.Display("Fox and Sheeps!", '#ccb684')
Board = Entities.Board()
Gameplay = None
GameplayThread = None


def Initialization():
    """ Each time we are refreshing the page, we're doing this """
    Display.Initialization(Board)


def Start():
    """ Equivalent to the action of the 'Start' button. Roughly making a new game play """
    global GameplayThread
    global DefaultFox
    global oncePressed
    global Gameplay
Ejemplo n.º 5
0
def train():
    # font for training
    font = pygame.font.SysFont('Comic Sans MS', TRAINING_TEXT_SIZE)

    # define a base and max moves-per-second (MPS)
    MPS = 20
    MIN_MPS = MPS
    MAX_MPS = MPS * 2**3

    # entities for training
    board = entities.Board(BOARD_WIDTH, BOARD_HEIGHT)
    for row in range(BOARD_HEIGHT):
        for column in range(BOARD_WIDTH):
            board.add_tile(entities.Tile(column * TILE_SIZE + TILE_MARGIN * column + TILE_MARGIN,\
             row * TILE_SIZE + TILE_MARGIN * row + TILE_MARGIN, TILE_SIZE, column, row, 'empty'))
    empty_button = entities.Button(WINDOW_WIDTH - 1.1 * TILE_BUTTON_SIZE,\
     TILE_BUTTON_SIZE, TILE_BUTTON_SIZE, TILE_BUTTON_SIZE)
    obstacle_button = entities.Button(WINDOW_WIDTH - 1.1 * TILE_BUTTON_SIZE,\
     TILE_BUTTON_SIZE + 1.5 * TILE_BUTTON_SIZE, TILE_BUTTON_SIZE, TILE_BUTTON_SIZE)
    reward_button = entities.Button(WINDOW_WIDTH - 1.1 * TILE_BUTTON_SIZE,\
     TILE_BUTTON_SIZE + 3 * TILE_BUTTON_SIZE, TILE_BUTTON_SIZE, TILE_BUTTON_SIZE)

    # loop variables
    in_training = True
    started = False
    decrease_randomness = True
    tile_choice = 'empty'
    current_key_pressed = None

    while in_training:
        # refresh background
        background.fill(TRAINING_BACKGROUND_COLOUR)

        # check for user mouse input
        for event in pygame.event.get():
            if event.type == pygame.QUIT:  # red 'x' at top of window clicked
                in_training = False
            if event.type == pygame.MOUSEBUTTONDOWN:  # mouse click
                mouse_position = event.pos
                if empty_button.collidepoint(mouse_position):
                    tile_choice = 'empty'
                elif obstacle_button.collidepoint(mouse_position):
                    tile_choice = 'obstacle'
                elif reward_button.collidepoint(mouse_position):
                    tile_choice = 'reward'
                elif board.tile_clicked(mouse_position):
                    board.change_tile_type(tile_choice)

        # handle key inputs from either both, or just one player
        keys = pygame.key.get_pressed()
        if keys[pygame.K_ESCAPE]:
            in_training = False
        elif keys[pygame.K_RETURN]:
            started = True
        elif keys[pygame.K_SPACE] and current_key_pressed != pygame.K_SPACE:
            decrease_randomness = False if decrease_randomness else True
            current_key_pressed = pygame.K_SPACE
        elif keys[pygame.K_RIGHT] and current_key_pressed != pygame.K_RIGHT:
            if MPS < MAX_MPS:
                MPS *= 2
            current_key_pressed = pygame.K_RIGHT
        elif keys[pygame.K_LEFT] and current_key_pressed != pygame.K_LEFT:
            if MPS > MIN_MPS:
                MPS /= 2
            current_key_pressed = pygame.K_LEFT
        else:
            current_key_pressed = None

        # draw the board
        board.draw_board(background)

        # update the board
        board.update(started, decrease_randomness)

        # display the buttons
        pygame.draw.rect(background, EMPTY_TILE_COLOUR, empty_button)
        pygame.draw.rect(background, OBSTACLE_TILE_COLOUR, obstacle_button)
        pygame.draw.rect(background, REWARD_TILE_COLOUR, reward_button)

        # display the % random moves and fast-forward speed
        display_text(font, str(abs(round(board.player.epsilon * 100, 1))) + "% Random",\
         (WINDOW_WIDTH - 100, WINDOW_HEIGHT - 50 - TRAINING_TEXT_SIZE), TRAINING_TEXT_COLOUR, centered = True)
        display_text(font, u"\u00d7" + str(MPS / MIN_MPS), (WINDOW_WIDTH - 50, WINDOW_HEIGHT - 50),\
         TRAINING_TEXT_COLOUR, centered = True)

        # update the window
        pygame.display.update()

        # wait to draw the next frame to ensure this frame is visible
        pygame.time.wait(int(1000 / MPS))
Ejemplo n.º 6
0
def Minimax(board, turn, depth):
    """ 
    Returns and action (start, end) which start and end are 2D tuples representing
    positions in the board.

    board -> Gets the current board and calculate on it.
    isFox -> Determining which side of the board (Sheep or fox) now taking a turn.
    window -> Getting the main window in the graphics for updating purposes.
    """
    """
    Minimax: Creates a table of decisions based on all available actions for each side of the 
    game. Tree is full and all parts should be there. We go as deep as we want (here is depth limited)
    and the reason is we cant go all the way through the tree because game trees are mostly considered unlimited.
    Then in any depth we want we stop and calculate Evaluation functions for tree leaves and then trace back
    the tree and run Minimax algorithm which is in each state, we either max or min over children based on whom turn
    it is. 
    """
    global algorithmBreak
    algorithmBreak = False

    isFox = True
    if (turn == Entities.Turn.Sheeps):
        isFox = False

    currentDepth = 0
    top = Entities.MinimaxTreeNode(currentDepth)
    top.actions = queue.Queue().queue

    # Going as deeply as we want, a depth limited. It can be break by minimaxBreak
    while (algorithmBreak == False and currentDepth != depth):

        # Getting all the noes in the current depth
        states = top.GetDepthNodes(currentDepth)
        if (states == None):
            break

        # Looping over all same depth nodes for updating board and make their children
        for s in states:
            # Creating a copy of the current board
            currentBoard = Entities.Board()
            currentBoard.Copy(board)
            priviousActions = s.actions.copy()

            # Loop over all actions  respectably in this state and update the board
            for i in range(s.actions.__len__()):
                action = s.actions.popleft()
                currentBoard.Action(action[0], action[1])

            availableActions = []
            # If this is fox turn
            if (isFox == True):
                availableActions = currentBoard.AvailableActionsFox()
            # If this is sheeps turn
            elif (isFox == False):
                availableActions = currentBoard.AvailableActionsSheep()

            # Loop over all available actions and for each make a child and assign to this state
            for a in availableActions:
                child = Entities.MinimaxTreeNode(currentDepth + 1)
                newActions = priviousActions.copy()
                newActions.append(a)
                child.actions = newActions
                child.parent = s
                s.AddChildren(child)

        currentDepth += 1
        isFox = not isFox

    # Filling the tree is done, now we select the appropriate action
    isFox = True
    if (turn == Entities.Turn.Sheeps):
        isFox = False

    TheNode = MiniMaxValue(board, top, isFox)

    # Returning the calculated action
    if (algorithmBreak == False):
        if (len(TheNode.actions) != 0):
            return TheNode.actions.popleft(), top
    else:
        algorithmBreak = False
Ejemplo n.º 7
0
def Deepimax(board, node, depth, maxDepth, isMax, doa, roa):
    """
    This is the algorithm i made to go as deep as we can while maintaining good decisions.
    """
    if (depth == 0 and node == None):
        node = Entities.DeepimaxTreeNode(0)
        node.actions = queue.Queue().queue

    # Creating a new instance of the board
    currentBoard = Entities.Board()
    currentBoard.Copy(board)
    previousActions = node.actions.copy()

    # Updating the board
    for i in range(previousActions.__len__()):
        action = previousActions.popleft()
        currentBoard.Action(action[0], action[1])

    # Get list of available actions
    availableActions = []
    if (isMax):
        availableActions = currentBoard.AvailableActionsFox()
    else:
        availableActions = currentBoard.AvailableActionsSheep()

    # Check the leave (We are in the last depth or we have no children)
    if (depth == maxDepth or availableActions.__len__() == 0
            or (roa == 0 and doa == 0)):
        node.point = currentBoard.EvaluationFunction()
        return node

    theNode = None
    tempChildren = []
    # Make the children
    for action in availableActions:
        child = Entities.DeepimaxTreeNode(node.depth + 1)
        newActions = node.actions.copy()
        newActions.append(action)
        child.actions = newActions
        if ((depth % doa) == 0 and depth != 0):
            tempChildren.append(child)
        else:
            child.parent = node
            node.AddChildren(child)

    # Actual Deepimax Algorithms
    if ((depth % doa) == 0 and depth != 0):
        # Expecting
        v = 0
        for child in tempChildren:
            temp = Deepimax(board, child, maxDepth, maxDepth, isMax, 0, 0)
            if (temp == None):
                continue
            v = v + temp.point
        node.point = v / tempChildren.__len__()
        return node
    else:
        for child in node.children:
            temp = Deepimax(board, child, depth + 1, maxDepth, not isMax, doa,
                            roa)
            if (temp == None):
                continue
            if ((depth % doa) == doa - 1):  # Collective
                node.nominies.append(temp)
                continue
            else:
                node.nominies += temp.nominies
        theNode = node

    if ((depth % doa) == 0):
        if (theNode.nominies.__len__() !=
                0):  # We have nominees, so we re engage again
            theNode.nominies = sorted(theNode.nominies,
                                      key=lambda x: x.point,
                                      reverse=isMax)

            # Re-engage for 'range of accuracy' times
            results = []
            theMaxDepth = maxDepth - doa

            if (doa > 1):
                doa -= 1

            currentRoa = roa
            if (currentRoa > 1):
                currentRoa -= 1

            for i in range(roa):
                if (i > theNode.nominies.__len__() - 1):
                    break

                # Call
                if (theMaxDepth == 0):
                    results.append(theNode.nominies[i])
                else:
                    temp = Deepimax(board, theNode.nominies[i], 0, theMaxDepth,
                                    not isMax, doa, currentRoa)
                    if (temp != None):
                        results.append(temp)

            result = None
            if (isMax):
                result = max(results, key=lambda x: x.point)
            else:
                result = min(results, key=lambda x: x.point)

            theNode.point = result.point
            return result

        else:
            return theNode
    else:
        return theNode
Ejemplo n.º 8
0
def Expectimax(board, node, depth, maxDebth, isMax, isExpect):
    """ The expectimax algorithm """
    # Creating the node
    if (depth == 0):
        node = Entities.MinimaxTreeNode(0)
        node.actions = queue.Queue().queue

    # Creating a new instance of the board
    currentBoard = Entities.Board()
    currentBoard.Copy(board)
    previousActions = node.actions.copy()

    # Updating the board
    for i in range(previousActions.__len__()):
        action = previousActions.popleft()
        currentBoard.Action(action[0], action[1])

    # Get list of available actions
    availableActions = []
    if (isMax):
        availableActions = currentBoard.AvailableActionsFox()
    else:
        availableActions = currentBoard.AvailableActionsSheep()

    # Check the leave (We are in the last depth or we have no children)
    if (depth == maxDebth or availableActions.__len__() == 0):
        node.point = currentBoard.EvaluationFunction()
        return node

    # Make the children
    for action in availableActions:
        child = Entities.MinimaxTreeNode(depth + 1)
        newActions = node.actions.copy()
        newActions.append(action)
        child.actions = newActions
        child.parent = node
        node.AddChildren(child)

    # Actual minimax with alpha beta pruning code
    if (not isExpect):  # Maximum
        v = -math.inf
        childNode = None
        for child in node.children:
            temp = Expectimax(board, child, depth + 1, maxDebth, not isMax,
                              True)
            if (temp == None):
                continue
            if (temp.point > v):
                childNode = temp
                v = temp.point
        node.point = v
        return childNode
    else:  # Expecting
        v = 0
        childNode = None
        for child in node.children:
            temp = Expectimax(board, child, depth + 1, maxDebth, not isMax,
                              False)
            if (temp == None):
                continue
            v = v + temp.point
        node.point = v / node.children.__len__()
        return node
Ejemplo n.º 9
0
def MinimaxAlphaBeta(board, node, depth, maxDebth, isMax, a, b):
    """ 
    The minimax Method with alpha beta pruning. 
    Returns a node
    """

    # Creating the node
    if (depth == 0):
        node = Entities.MinimaxTreeNode(0)
        node.actions = queue.Queue().queue

    # Creating a new instance of the board
    currentBoard = Entities.Board()
    currentBoard.Copy(board)
    previousActions = node.actions.copy()

    # Updating the board
    for i in range(previousActions.__len__()):
        action = previousActions.popleft()
        currentBoard.Action(action[0], action[1])

    # Get list of available actions
    availableActions = []
    if (isMax):
        availableActions = currentBoard.AvailableActionsFox()
    else:
        availableActions = currentBoard.AvailableActionsSheep()

    # Check the leave (We are in the last depth or we have no children)
    if (depth == maxDebth or availableActions.__len__() == 0):
        node.point = currentBoard.EvaluationFunction()
        return node

    # Make the children
    for action in availableActions:
        child = Entities.MinimaxTreeNode(depth + 1)
        newActions = node.actions.copy()
        newActions.append(action)
        child.actions = newActions
        child.parent = node
        node.AddChildren(child)

    # Actual minimax with alpha beta pruning code
    if (isMax):
        v = -math.inf
        childNode = None
        for child in node.children:
            temp = MinimaxAlphaBeta(board, child, depth + 1, maxDebth, False,
                                    a, b)
            if (temp == None):
                continue
            if (temp.point > v):
                childNode = temp
                v = temp.point
            if (v >= b):
                return None
            a = max(a, v)
        node.point = v
        return childNode
    else:
        v = math.inf
        childNode = None
        for child in node.children:
            temp = MinimaxAlphaBeta(board, child, depth + 1, maxDebth, True, a,
                                    b)
            if (temp == None):
                continue
            if (temp.point < v):
                childNode = temp
                v = temp.point
            if (v <= a):
                return None
            b = min(a, v)
        node.point = v
        return childNode