Beispiel #1
0
def board(request, game_id):
    """
    Returns the current game board state.
    :param request:
    :param game_id: unique identifier of the board
    :return game board JSON:
    """

    response_status = utils.load_board_db(game_id)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_400_BAD_REQUEST)

    # hide the UID used by data structure backend from user
    # del response_status['game_board']['graph']['uid']

    return Response(response_status['game_board'])
Beispiel #2
0
def move_food(request, game_id, start, dest):
    """
    Moves food from start chamber to destination chamber
    :param game_id: unique identifier of the board
    :param start: The chamber to move the food from.
    :param dest: the chamber where the food should be placed
    :return game board JSON:
    """

    # Load the game board from database
    response_status = utils.load_board_db(game_id)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    board = response_status['game_board']

    # Make sure that the player isn't trying to move to or from surface.
    if start == 'surface' or dest == 'surface':
        return Response({'invalid_action': 'no food on surface allowed'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If start and dest don't exist for some reason
    if start not in board['graph']['chambers'] or dest not in board['graph'][
            'chambers']:
        return Response({'invalid_action': 'invalid chambers'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If chambers aren't connected then return
    if board['graph']['chambers'][start]['tunnels']['next'] != dest:
        return Response({'invalid_action': 'no tunnel'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If there is no queen then game over actually
    if not board['queen_at_head']:
        return Response({'invalid_action': 'game over'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If there are no chambers player can't move food
    if board['total_chambers'] == 1:
        return Response({'invalid_action': 'no chambers'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If there are no ants in the start chamber then can't move food
    if board['graph']['chambers'][start]['num_ants'] == 0:
        return Response({'invalid_action': 'no ants'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If the requested dest chamber is under attack then can't move food
    if board['graph']['chambers'][dest]['under_attack']:
        return Response({'invalid_action': 'under attack'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If there is no food in the starting chamber then you can't move food
    if board['graph']['chambers'][start]['food']['total'] == 0:
        return Response({'invalid_action': 'no food'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If the player can't make a move, return error
    if board['time_tracks']['move/forage'] == 0:
        return Response({'invalid_action': 'no time'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If we were to make it so that the user can only fit up to 6 food in the each
    # chamber, this might cause an issue with the fact that ants can only move one spot
    # So I will move food to the next chamber, not matter how much food is in the next chamber

    # 'Pick up' the first available food of the highest value.
    # Only allowing the player to move one piece of food at a time, while having no food
    # limit for chambers, still ensures that the player is motivated to not cram all food into
    # on chamber.
    food_picked_up = ''
    value = 0
    if board['graph']['chambers'][start]['food']['donut'] > 0:
        board['graph']['chambers'][start]['food']['donut'] -= 1
        board['graph']['chambers'][start]['food']['total'] -= 3
        food_picked_up = 'donut'
        value = 3

    elif board['graph']['chambers'][start]['food']['berry'] > 0:
        board['graph']['chambers'][start]['food']['berry'] -= 1
        board['graph']['chambers'][start]['food']['total'] -= 2
        food_picked_up = 'berry'
        value = 2

    elif board['graph']['chambers'][start]['food']['crumb'] > 0:
        board['graph']['chambers'][start]['food']['crumb'] -= 1
        board['graph']['chambers'][start]['food']['total'] -= 1
        food_picked_up = 'crumb'
        value = 1

        # Put food in the destination chamber
    board['graph']['chambers'][dest]['food'][food_picked_up] += 1
    board['graph']['chambers'][dest]['food']['total'] += value

    # Update ant locations
    board['graph']['chambers'][start]['num_ants'] -= 1
    board['graph']['chambers'][dest]['num_ants'] += 1

    # Decrement Move/Forage time track
    board['time_tracks']['move/forage'] -= 1

    user_id = board['player_ids']
    token = -1
    # Update the board on database
    response_status = utils.update_board_db(board, user_id, token)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    board_response = response_status['game_board']
    return Response(board_response)
Beispiel #3
0
def move_ant(request, game_id, start, dest):
    """
    Moves ant from start chamber to destination chamber
    :param game_id: unique identifier of the board
    :param start: The chamber to move from.
    :param dest: the chamber where to move
    :return game board JSON:
    """

    # Load the game board from database
    response_status = utils.load_board_db(game_id)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    board = response_status['game_board']

    # If start and dest don't exist for some reason
    if (start not in board['graph']['chambers']) or (
            dest not in board['graph']['chambers']):
        return Response({'invalid_action': 'invalid chambers'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If chambers aren't connected then return
    if board['graph']['chambers'][start]['tunnels']['next'] != dest:
        return Response({'invalid_action': 'no tunnel'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If there is no queen then game over actually
    if board['queen_at_head'] == False:
        return Response({'invalid_action': 'game over'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If no ant to move
    if board['graph']['chambers'][start]['num_ants'] == 0:
        return Response({'invalid_action': 'no ants'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If the player can't make a move, return error
    if board['time_tracks']['move/forage'] == 0:
        return Response({'invalid_action': 'no time'},
                        status=status.HTTP_400_BAD_REQUEST)

    # if at this point, update all relevant game board values
    # Update ant locations
    board['graph']['chambers'][start]['num_ants'] -= 1
    board['graph']['chambers'][dest]['num_ants'] += 1

    if start == 'surface':
        board['total_surface_ants'] -= 1

    # Decrement Move/Forage time track
    board['time_tracks']['move/forage'] -= 1

    user_id = board['player_ids']
    token = -1
    # Update the board on database
    response_status = utils.update_board_db(board, user_id, token)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    board_response = response_status['game_board']
    return Response(board_response)
Beispiel #4
0
def forage(request, game_id, difficulty, dest):
    """
    Spawns an ant given the game ID
    :param game_id: unique identifier of the board
    :param difficulty: game difficulty
    :param ant_loc: the chamber in which the ant is located
    :param dest: the chamber where the food should be placed
    :return game board JSON:
    """

    # Load the game board from database
    response_status = utils.load_board_db(game_id)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    board = response_status['game_board']

    # Make sure that the destination chamber is in the colony
    if dest not in board['graph']['chambers']:
        return Response({'invalid_action': 'dest dne'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Make sure that the surface is connected to the dest somehow.
    curr_chamber = 'surface'
    connected = False
    while board['graph']['chambers'][curr_chamber]['tunnels']['next'] is not None and \
            board['graph']['chambers'][curr_chamber]['tunnels']['next'] != 'surface':
        if board['graph']['chambers'][curr_chamber]['tunnels']['next'] == dest:
            connected = True
            break
        curr_chamber = board['graph']['surface'][curr_chamber]['tunnels'][
            'next']

    if connected == False:
        return Response({'invalid_action': 'dest unreachable'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If there are no chambers player can't forage
    if board['total_chambers'] == 0:
        return Response({'invalid_action': 'no chambers'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If there is no queen then game over actually
    if board['queen_at_head'] == False:
        return Response({'invalid_action': 'lost queen'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If there are no worker ants on the surface.
    if board['total_surface_ants'] == 1:
        return Response({'invalid_action': 'no surface ants'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If the requested chamber is under attack return error
    if board['graph']['chambers'][dest]['under_attack']:
        return Response({'invalid_action': 'under attack'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If the player can't make a forage move, return error
    if board['time_tracks']['move/forage'] == 0:
        return Response({'invalid_action': 'no time'},
                        status=status.HTTP_400_BAD_REQUEST)

    # choose a random number then choose the forage type that will be returned
    rand_food = random.randint(0, 100)
    crumb_chance = config.FORAGE_CHANCE[difficulty][config.FORAGE_TYPES[0]]
    berry_chance = config.FORAGE_CHANCE[difficulty][config.FORAGE_TYPES[1]]
    donut_chance = config.FORAGE_CHANCE[difficulty][config.FORAGE_TYPES[2]]
    attack_chance = config.FORAGE_CHANCE[difficulty][config.FORAGE_TYPES[3]]

    # Check if crumb was chosen
    if rand_food >= 0 and rand_food < crumb_chance:
        forage_result = config.FORAGE_TYPES[0]

    # Check if berry was chosen
    if rand_food >= crumb_chance and rand_food < berry_chance:
        forage_result = config.FORAGE_TYPES[1]

    # Check if donut was chosen
    if rand_food >= berry_chance and rand_food < donut_chance:
        forage_result = config.FORAGE_TYPES[2]

    # Check if attack was chosen
    if rand_food >= donut_chance and rand_food < attack_chance:
        forage_result = config.FORAGE_TYPES[3]

    # If the forage resulted in the chamber coming under attack,
    # Then reflect the change in the board
    if forage_result == config.FORAGE_TYPES[3]:
        board['graph']['chambers'][dest]['under_attack'] = True
        board['total_under_attack'] += 1
        board['total_surface_ants'] -= 1
        board['graph']['chambers']['surface']['num_ants'] -= 1
        board['graph']['chambers'][dest]['num_ants'] += 1

    # Otherwise, put the food in the requested chamber, move the ant, and update the board
    else:
        # Change food in requested chamber
        board['graph']['chambers'][dest]['food'][forage_result] += 1
        board['graph']['chambers'][dest]['food']['total'] += config.FOOD_VALUE[
            forage_result]

        # Change food stats on for the game board
        board['total_food_types'][forage_result] += 1
        board['total_food'] += config.FOOD_VALUE[forage_result]

        # Move the ant from og spot to new spot
        board['total_surface_ants'] -= 1
        board['graph']['chambers']['surface']['num_ants'] -= 1
        board['graph']['chambers'][dest]['num_ants'] += 1

    # Decrement Move/Forage time track
    board['time_tracks']['move/forage'] -= 1

    user_id = board['player_ids']
    token = -1
    # Update the board on database
    response_status = utils.update_board_db(board, user_id, token)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    board_response = response_status['game_board']
    return Response(board_response)
Beispiel #5
0
def spawn_ant(request, game_id):
    """
    Spawns an ant given the game ID
    :param game_id: unique identifier of the board
    :return game board JSON:
    """

    # Load the game board from database
    response_status = utils.load_board_db(game_id)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    board = response_status['game_board']

    if not board['queen_at_head']:
        return Response({'invalid_action': 'lost queen'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Make sure there is enough food to spawn a new ant
    if board['total_food'] < config.ANT_SPAWN_VAL:
        return Response({'invalid_action': 'not enough food'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Take away food, if they have food that can be
    curr_food_types = board['total_food_types']

    # Find the first chamber with enough food
    chamber_with_food = None
    for chamber in board['graph']['chambers'].keys():
        if chamber != 'surface' and board['graph']['chambers'][chamber][
                'food']['total'] >= config.ANT_SPAWN_VAL:
            chamber_with_food = chamber
            break

    # If player has a donut take it
    if curr_food_types[config.FORAGE_TYPES[2]] > 0:
        board['total_food_types'][config.FORAGE_TYPES[2]] -= 1
        board['total_food'] -= config.ANT_SPAWN_VAL

        board['graph']['chambers'][chamber_with_food]['food'][
            config.FORAGE_TYPES[2]] -= 1
        board['graph']['chambers'][chamber_with_food]['food'][
            'total'] -= config.ANT_SPAWN_VAL

    # If player has at least one berry and one crumb, take one of each
    elif curr_food_types[config.FORAGE_TYPES[1]] > 0 and curr_food_types[
            config.FORAGE_TYPES[0]] > 0:
        board['total_food_types'][config.FORAGE_TYPES[1]] -= 1
        board['total_food_types'][config.FORAGE_TYPES[0]] -= 1
        board['total_food'] -= config.ANT_SPAWN_VAL

        board['graph']['chambers'][chamber_with_food]['food'][
            config.FORAGE_TYPES[1]] -= 1
        board['graph']['chambers'][chamber_with_food]['food'][
            config.FORAGE_TYPES[0]] -= 1
        board['graph']['chambers'][chamber_with_food]['food'][
            'total'] -= config.ANT_SPAWN_VAL

    # If player only has crumbs take it
    elif curr_food_types[config.FORAGE_TYPES[0]] >= config.ANT_SPAWN_VAL:
        board['total_food_types'][
            config.FORAGE_TYPES[0]] -= config.ANT_SPAWN_VAL
    # If this case is reached, the player has enough food, but only in berry form (not divisible by 3)
    elif curr_food_types[config.FORAGE_TYPES[1]] >= 2:
        board['total_food_types'][config.FORAGE_TYPES[1]] -= 2
        board['total_food_types'][config.FORAGE_TYPES[0]] += 1
        board['total_food'] -= config.ANT_SPAWN_VAL

        board['graph']['chambers'][chamber_with_food]['food'][
            config.FORAGE_TYPES[1]] -= 2
        board['graph']['chambers'][chamber_with_food]['food'][
            config.FORAGE_TYPES[1]] += 1
        board['graph']['chambers'][chamber_with_food]['food'][
            'total'] -= config.ANT_SPAWN_VAL
    else:
        return Response({'invalid_action': 'error occurred'},
                        status=status.HTTP_400_BAD_REQUEST)

    # if control reaches here, then spawning an ant is successful. Update both total and surface ant values.
    board['total_ants'] += 1
    board['total_surface_ants'] += 1
    action = ['spawn_ant']
    board['graph'] = doAction(board['graph'], action)

    user_id = board['player_ids']
    token = -1
    # Update the board on database
    response_status = utils.update_board_db(board, user_id, token)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    board_response = response_status['game_board']
    return Response(board_response)
Beispiel #6
0
def fill_chamber(request, game_id, to_fill):
    """
    Attempts to 'fill' (delete) a chamber and all associated tunnels
    :param game_id: unique identifier of the board
    :param to_fill: the chamber that the player wishes to delete
    :return game board JSON:
    """

    # Check if game exists
    # Load the game board from database
    response_status = utils.load_board_db(game_id)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    board = response_status['game_board']

    # Check if to_fill is surface (cannot fill in surface)
    if to_fill == 'surface':
        return Response({'invalid_action': 'cannot fill in surface'},
                        status=status.HTTP_400_BAD_REQUEST)
    # Check if to_fill exists
    if to_fill not in board['graph']['chambers']:
        return Response({'invalid_action': 'chamber does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Check for fill chamber energy
    if board['time_tracks']['dig/fill_chamber'] == 0:
        return Response({'invalid_action': 'no more fill chamber moves left!'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Check if to_fill has any food in it
    if (board['graph']['chambers'][to_fill]['food']['crumb'] > 0) \
            or (board['graph']['chambers'][to_fill]['food']['berry'] > 0) \
            or (board['graph']['chambers'][to_fill]['food']['donut'] > 0):
        return Response({'invalid_action': 'There is food in this chamber!'},
                        status=status.HTTP_400_BAD_REQUEST)
    # Check if there is at least one ant at the prev chamber
    previous = board['graph']['chambers'][to_fill]['tunnels']['prev']
    if board['graph']['chambers'][previous]['num_ants'] == 0:
        return Response({'invalid_action': 'No ant in previous chamber!'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Check if there is a next chamber, and if so, if there is at least one ant in it
    if board['graph']['chambers'][to_fill]['tunnels']['next'] is not None:
        next_chamber = board['graph']['chambers'][to_fill]['tunnels']['next']
        if board['graph']['chambers'][next_chamber]['num_ants'] == 0:
            return Response({'invalid_action': 'No ant in next chamber!'},
                            status=status.HTTP_400_BAD_REQUEST)

    # If at this point, all checks are made. Update gameboard
    # link up prev and next
    board['graph'] = doAction(board['graph'], ('fill_chamber', to_fill))

    board['total_chambers'] -= 1
    board['time_tracks']['dig/fill_chamber'] -= 1

    user_id = board['player_ids']
    token = -1
    # Update the board on database
    response_status = utils.update_board_db(board, user_id, token)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    board_response = response_status['game_board']
    return Response(board_response)
Beispiel #7
0
def dig_chamber(request, game_id, origin, move_ant, ant=None):
    """
    Attempts to dig a new chamber off of a current dead-end tunnel
    :param game_id: unique identifier of the board
    :param origin: the chamber that the player wishes to dig from
    :param move_ant: whether the player wishes to move the ant into the new chamber
    """
    # checklist
    if ant == 'None':
        ant = None

    # Check if game exists
    response_status = utils.load_board_db(game_id)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    board = response_status['game_board']

    # Check for dig chamber energy
    if board['time_tracks']['dig/fill_chamber'] == 0:
        return Response({'invalid_action': 'no more dig chamber moves left!'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Check if move_ant is a valid input
    if move_ant != 'yes':
        if move_ant != 'no':
            return Response({'invalid_action': 'invalid free move request!'},
                            status=status.HTTP_400_BAD_REQUEST)

    # Check if origin exists
    if origin != 'surface' and origin not in board['graph']['chambers']:
        return Response({'invalid_action': 'origin does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)

    # check if origin contains at least one ant
    if origin == 'surface' and board['total_surface_ants'] == 1:
        return Response({'invalid_action': 'no ants on surface'},
                        status=status.HTTP_400_BAD_REQUEST)
    if board['graph']['chambers'][origin]['num_ants'] == 0:
        return Response({'invalid_action': 'no ants at origin'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Check if origin contains an exit tunnel
    if board['graph']['chambers'][origin]['tunnels']['next'] is not None:
        return Response({'invalid_action': 'no available tunnel from origin'},
                        status=status.HTTP_400_BAD_REQUEST)
    # if origin contains a next tunnel, check if current next is 'none'
    # if board['graph']['tunnels'][origin][0] == 2 and board['graph']['tunnels'][origin][2] is not None:
    #     return Response({'invalid_action': 'no available tunnel from origin'},
    #                     status=status.HTTP_400_BAD_REQUEST)

    # if at this point, dig request is valid: update ALL relevant game board variables
    newchamberid = 'chamber' + str(len(board['graph']['chambers'].keys()) + 1)
    board['graph'] = doAction(board['graph'], ('dig_chamber', origin))
    board['total_chambers'] += 1

    if move_ant == 'yes' and ant is not None:
        board['graph'] = doAction(board['graph'],
                                  ('move_ant', ant, newchamberid))

    board['time_tracks']['dig/fill_chamber'] -= 1

    user_id = board['player_ids']
    token = -1
    # Update the board on database
    response_status = utils.update_board_db(board, user_id, token)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    board_response = response_status['game_board']
    return Response(board_response)
Beispiel #8
0
def dig_tunnel(request, game_id, origin, destination):
    """
    Attempts to dig a tunnel from the requested chamber to a requested destination
    :param game_id: unique identifier of the board
    :param origin: the chamber that the player wishes to dig from
    :param destination: the place that the player wishes to dig to (chamber name, 'surface', or 'none'
    """
    # convert string to actual value
    if destination == 'None':
        destination = None

    # Game must exist
    # Load the game board from database
    response_status = utils.load_board_db(game_id)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    board = response_status['game_board']

    # origin and destination MUST be different
    if origin == destination:
        return Response({'invalid_action': 'origin cannot match destination'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Player must still have dig 'energy' for that day
    if board['time_tracks']['dig_tunnel_track'] == 0:
        return Response({'invalid_action': 'no more dig tunnel moves left!'},
                        status=status.HTTP_400_BAD_REQUEST)
    # Origin must exist
    if origin != 'surface' and origin not in board['graph']['chambers']:
        return Response({'invalid_action': 'origin does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If destination is NOT 'none', it must exist (chamber OR surface)
    if destination is not None and destination not in board['graph'][
            'chambers']:
        return Response({'invalid_action': 'destination does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If Origin is surface, colony_entrance MUST be False
    if origin == 'surface' and board['colony_entrance'] is True:
        return Response({'invalid_action': 'colony_entrance already exists'},
                        status=status.HTTP_400_BAD_REQUEST)

    # There must be at least one ant at origin
    if origin == 'surface' and board['total_surface_ants'] == 0:
        return Response({'invalid_action': 'no ants on surface'},
                        status=status.HTTP_400_BAD_REQUEST)
    if board['graph']['chambers'][origin]['num_ants'] == 0:
        return Response({'invalid_action': 'no ants at origin'},
                        status=status.HTTP_400_BAD_REQUEST)

    # If destination is NOT none, there must be an ant at the destination
    if destination is not None and board['graph']['chambers'][destination][
            'num_ants'] == 0:
        return Response({'invalid_action': 'no ants at destination'},
                        status=status.HTTP_400_BAD_REQUEST)

    # Origin chamber must NOT already have an exit tunnel, except if it's to the surface
    if board['graph']['chambers'][origin]['tunnels']['next'] is not None and \
            board['graph']['chambers'][origin]['tunnels']['next'] != 'surface':
        return Response({'invalid_action': 'exit tunnel exists'},
                        status=status.HTTP_400_BAD_REQUEST)

    # destination must NOT already have an entrance tunnel
    if destination is not None and board['graph']['chambers'][destination][
            'tunnels']['prev'] is not None:
        return Response({'invalid_action': 'exit tunnel exists'},
                        status=status.HTTP_400_BAD_REQUEST)

    # if ALL checks are passed, create new tunnel and update ALL relevant gameboard parameters

    # num_tunnels
    board['graph'] = doAction(board['graph'],
                              ('dig_tunnel', origin, destination))
    board['total_tunnels'] += 1

    if origin == 'surface':
        board['colony_entrance'] = True
    if destination == 'surface':
        board['colony_exit'] = True

    board['time_tracks']['dig_tunnel_track'] -= 1

    user_id = board['player_ids']
    token = -1

    # Update the board on database
    response_status = utils.update_board_db(board, user_id, token)
    if response_status['error']:
        return Response({'error': response_status['reason']},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    board_response = response_status['game_board']
    return Response(board_response)