예제 #1
0
def use_robber(player, robber, hexes, boardSurface, playerKey, menuSurface, titleFont, infoFont):
    # Get the current hex of the Robber to use as a metric to know when the player has successfully picked a new hex
    destinationHex = robber.currentHex
    print("Choose a new hex for the Robber.")
    # Ask the player to which hex they want to move the Robber
    destinationHex = ui.get_hex_from_player(player, hexes, playerKey)
    if destinationHex is None:
        return (1, "{} did not choose a hex.".format(player.name))
    # A list to hold the players from whom the player can steal
    playersAvailableToRob = []
    # Loop through the vertices that surround the Robber's new hex
    for vertex in destinationHex.vertices:
        # Check whether each vertex has a settlement built on it
        if vertex.settlement is not None:
            # If so, check that the owner of that settlement is not the player
            if vertex.settlement.owner != player and vertex.settlement.owner not in playersAvailableToRob:
                # If that's the case, the owner of that vertex is a player from whom the player can steal
                playersAvailableToRob.append(vertex.settlement.owner)
    # The default value for the player from whom the player will steal
    playerToRob = None
    # If the player has multiple players from whom they can steal, ask them to choose their target
    if len(playersAvailableToRob) > 0:
        print("Choose the player from whom you wish to steal.")
        playerMenu = {"Cancel and return to main menu": None}
        for plyr in playersAvailableToRob:
            playerMenu["{} ({} cards)".format(plyr.name, sum(plyr.cardsInHand.values()))] = plyr
        playerToRob = ui.present_menu(player, playerMenu, "Steal from", menuSurface, titleFont, infoFont)
        if playerToRob is None:
            return (2, "{} did not choose a player.".format(player.name))
    robberResult = robber.play(boardSurface, destinationHex, player, playerToRob)
    return (0, robberResult)
예제 #2
0
def halve_player_hand(player, playerList, resourceDecks, handSurface, menuSurface, enemySurface, titleFont, infoFont):
    handSurface.fill(c.white)
    ui.present_menu(player, {"Yes": 1}, "Ready?", menuSurface, titleFont, infoFont)
    draw_player_hand(player, handSurface, titleFont, infoFont)
    draw_enemy_info(player, playerList, enemySurface, infoFont)
    pygame.display.update(handSurface.get_rect())
    numToDiscard = int(sum(player.cardsInHand.values()) / 2.0)
    while numToDiscard > 0:
        resourcesInHand = sorted([resource for resource in player.cardsInHand.keys()
                                  if player.cardsInHand[resource] > 0])
        resourceMenu = OrderedDict(zip(resourcesInHand, resourcesInHand))
        cardToDiscard = ui.present_menu(player, resourceMenu, "Discard {}".format(numToDiscard), menuSurface, titleFont,
                                        infoFont)
        player.discard_resources({cardToDiscard: 1}, resourceDecks)
        draw_player_hand(player, handSurface, titleFont, infoFont)
        pygame.display.update(handSurface.get_rect())
        numToDiscard -= 1
    return (0, "{} successfully discarded cards.".format(player.name))
예제 #3
0
def play_yop_card(player, resourceDecks, surface, titleFont, infoFont):
    if not player.has_dev_card("Year of Plenty"):
        if player.has_new_dev_card("Year of Plenty"):
            return (1, "Cannot play a Development Card on the turn it's bought.")
        return (1, "{} does not have a Year of Plenty to play.".format(player.name))
    availableResources = [resource for resource in resourceDecks.keys() if resourceDecks[resource] > 0]
    resourceMenu = OrderedDict(zip(availableResources, availableResources))
    resourceMenu["Cancel and return to main menu"] = None
    print("{}, choose the first resource to draw.".format(player.name))
    resource1 = ui.present_menu(player, resourceMenu, "Draw Which? (1)", surface, titleFont, infoFont)
    if resource1 is None:
        return (2, "{} chose to not play a Year of Plenty.".format(player.name))
    player.draw_resources({resource1: 1}, resourceDecks)
    player.consume_dev_card("Year of Plenty")
    availableResources = [resource for resource in resourceDecks.keys() if resourceDecks[resource] > 0]
    resourceMenu = OrderedDict(zip(availableResources, availableResources))
    resourceMenu["Don't draw a 2nd card"] = None
    print("{}, choose the second resource to draw.".format(player.name))
    resource2 = ui.present_menu(player, resourceMenu, "Draw Which? (2)", surface, titleFont, infoFont)
    if resource2 is None:
        return (0, "{} used Year of Plenty to draw {}".format(player.name, resource1))
    player.draw_resources({resource2: 1}, resourceDecks)
    return (0, "{} used Year of Plenty to draw {} and {}".format(player.name, resource1, resource2))
예제 #4
0
def maritime_trade(player, resourceDecks, surface, titleFont, infoFont):
    tradeAwayList = []
    for resource in c.resourceTypes:
        ratio = player.tradeRatios[resource]
        if player.cardsInHand[resource] >= ratio:
            tradeAwayList.append(("{} at {} to 1".format(resource, ratio), resource))
    tradeAwayList.append(("Cancel and return to main menu", None))
    tradeAwayMenu = OrderedDict(tradeAwayList)
    print("Please select the resource you would like to maritime trade: ")
    resourceTrading = ui.present_menu(player, tradeAwayMenu, "Trade Away", surface, titleFont, infoFont)
    if resourceTrading is None:
        return (1, "{} chose not to trade.".format(player.name))
    tradeRatio = player.tradeRatios[resourceTrading]
    tradeForList = []
    for resource in c.resourceTypes:
        if resource is not resourceTrading and resourceDecks[resource] > 0:
            tradeForList.append((resource, resource))
    tradeForList.append(("Cancel and return to main menu", None))
    tradeForMenu = OrderedDict(tradeForList)
    resourceGetting = ui.present_menu(player, tradeForMenu, "Trade For", surface, titleFont, infoFont)
    if resourceGetting is None:
        return (1, "{} chose not to trade.".format(player.name))
    tradeAmountList = []
    counter = 1
    while counter * tradeRatio <= player.cardsInHand[resourceTrading] and counter <= resourceDecks[resourceGetting]:
        tradeAmountList.append(("{} {} for {} {}".format(counter * tradeRatio, resourceTrading, counter,
                                                         resourceGetting), counter))
        counter += 1
    tradeAmountList.append(("Cancel and return to main menu", None))
    tradeAmountMenu = OrderedDict(tradeAmountList)
    tradeQuantity = ui.present_menu(player, tradeAmountMenu, "Trade", surface, titleFont, infoFont)
    if tradeQuantity is None:
        return (1, "{} chose not to trade.".format(player.name))
    player.discard_resources({resourceTrading: tradeQuantity * tradeRatio}, resourceDecks)
    player.draw_resources({resourceGetting: tradeQuantity}, resourceDecks)
    return (0, "{} traded {} {} for {} {}".format(player.name, tradeQuantity * tradeRatio, resourceTrading,
                                                  tradeQuantity, resourceGetting))
예제 #5
0
def play_monopoly_card(player, resourceDecks, playerList, surface, titleFont, infoFont):
    if not player.has_dev_card("Monopoly"):
        if player.has_new_dev_card("Monopoly"):
            return (1, "Cannot play a Development Card on the turn it's bought.")
        return (1, "{} does not have a Monopoly card to play.".format(player.name))
    print("{}, which resource do you want to monopolize?".format(player.name))
    resourceMenu = OrderedDict(zip(c.resourceTypes, c.resourceTypes))
    resourceMenu["Cancel and return to main menu"] = None
    choice = ui.present_menu(player, OrderedDict(zip(c.resourceTypes, c.resourceTypes)), "Take Which?", surface,
                             titleFont, infoFont)
    if choice is None:
        return (2, "{} cancelled the play. Returning.")
    startCount = player.cardsInHand[choice]
    enemyList = [person for person in playerList if person != player]
    for enemy in enemyList:
        enemyResourceCount = enemy.cardsInHand[choice]
        enemy.discard_resources({choice: enemyResourceCount}, resourceDecks)
        player.draw_resources({choice: enemyResourceCount})
    gain = player.cardsInHand[choice] - startCount
    return (0, "{} drew {} {} from the other players.".format(player.name, gain, choice))
예제 #6
0
def main():

    # A dictionary to hold the decks of resources, keyed to their resource name
    resourceDecks = {c.lumber: 19, c.grain: 19, c.wool: 19, c.clay: 19, c.ore: 19}
    developmentDeck = deque(c.developmentDeckList)

    # A list of the hexes, assigned a resource and a numbered tile using the lists above
    hexes = [p.Hex(c.resourcesForHexes[x], c.oddsOrdered[x], c.resourceToColor[c.resourcesForHexes[x]], c.hexCenters[x])
             for x in range(19)]
    # Iterate over the hexes and create Vertex objects using the coordinates of their vertices
    vertices = []
    vertexCoordsSeen = []
    # Loop over the top 3 rows of hexes
    for hexTile in hexes[:12]:
        # Loop over the coordinates of the upper 3 vertices
        for index, coord in enumerate(hexTile.vertexCoordinates[:3]):
            # Check that this is a new vertex coordinate
            if coord not in vertexCoordsSeen:
                # Record this vertex position
                vertexCoordsSeen.append(coord)
                # Create a new Vertex object at these coordinates
                newVertex = p.Vertex(coord)
                # Check that the vertex is not the upper-left vertex of the hex
                # If not, record that this vertex is adjacent to the previous vertex
                if index != 0:
                    vertices[-1].adjacentVertices.append(newVertex)
                    newVertex.adjacentVertices.append(vertices[-1])
                # Add the vertex to the list of vertices
                vertices.append(newVertex)
    # Repeat the loop above for the bottom three rows of hexes
    for hexTile in hexes[7:]:
        # Use the lower 3 coordinates here
        for index, coord in enumerate(hexTile.vertexCoordinates[3:][::-1]):
            if coord not in vertexCoordsSeen:
                vertexCoordsSeen.append(coord)
                newVertex = p.Vertex(coord)
                if index != 0:
                    vertices[-1].adjacentVertices.append(newVertex)
                    newVertex.adjacentVertices.append(vertices[-1])
                vertices.append(newVertex)
    # Loop through the vertices and relate them to the hexes they touch
    for vertex in vertices:
        # For each vertex, look at hex
        for hexTile in hexes:
            # Check that the vertex and hex aren't already related but the coordinates match
            if vertex not in hexTile.vertices and vertex.coordinates in hexTile.vertexCoordinates:
                # Record the position of the vertex according to the hex's coordinate list
                verIndex = hexTile.vertexCoordinates.index(vertex.coordinates)
                # Place the vertex into the hex's vertex list at the same position
                hexTile.vertices[verIndex] = vertex
                # Add the hex to the vertex's hex list
                vertex.hexes.append(hexTile)
                # If the vertex has 3 hexes in its hex list, no more hexes need to be examined
                if len(vertex.hexes) == 3:
                    break
    # Loop through the hexes and relate vertices that are vertically adjacent
    for hexTile in hexes:
        if hexTile.vertices[0] not in hexTile.vertices[5].adjacentVertices:
            hexTile.vertices[0].adjacentVertices.append(hexTile.vertices[5])
            hexTile.vertices[5].adjacentVertices.append(hexTile.vertices[0])
        if hexTile.vertices[2] not in hexTile.vertices[3].adjacentVertices:
            hexTile.vertices[2].adjacentVertices.append(hexTile.vertices[3])
            hexTile.vertices[3].adjacentVertices.append(hexTile.vertices[2])

    # A list of the ports on the map
    ports = [p.Port([resource], 2) for resource in c.resourceTypes]
    ports += [p.Port(list(c.resourceTypes), 3) for i in range(4)]
    # Assign the ports to the appropriate vertices
    vertices[0].port = ports[5]
    vertices[1].port = ports[5]
    ports[5].vertices = [vertices[0], vertices[1]]
    vertices[3].port = ports[2]
    vertices[4].port = ports[2]
    ports[2].vertices = [vertices[3], vertices[4]]
    vertices[7].port = ports[4]
    vertices[14].port = ports[6]
    vertices[15].port = ports[6]
    ports[6].vertices = [vertices[14], vertices[15]]
    vertices[17].port = ports[4]
    ports[4].vertices = [vertices[7], vertices[17]]
    vertices[26].port = ports[7]
    vertices[28].port = ports[1]
    vertices[37].port = ports[7]
    vertices[38].port = ports[1]
    ports[7].vertices = [vertices[26], vertices[37]]
    ports[1].vertices = [vertices[28], vertices[38]]
    vertices[45].port = ports[3]
    vertices[46].port = ports[3]
    ports[3].vertices = [vertices[45], vertices[46]]
    vertices[47].port = ports[8]
    vertices[48].port = ports[8]
    ports[8].vertices = [vertices[47], vertices[48]]
    vertices[50].port = ports[0]
    vertices[51].port = ports[0]
    ports[0].vertices = [vertices[50], vertices[51]]

    # Create the Robber
    robber = p.Robber(hexes[c.desertIndex])

    # Instantiate a player with their name, color, AI status, and the sizes of their pieces
    playerList = ui.create_players()
    # Give the players enough cards to build their first settlements and roads
    # TODO EDITED THIS TO TEST MARITIME TRADING & BUILDING
    startingHand = {c.grain: 4, c.wool: 2, c.clay: 4, c.lumber: 4, c.ore: 3}
    for player in playerList:
        player.draw_resources(startingHand, resourceDecks)
    # Shuffle the players to set the turn order
    random.shuffle(playerList)

    # Set up the award placards
    largestArmy = p.LargestArmy(playerList)
    longestRoad = p.LongestRoad(playerList)

    # Pygame initialization
    pygame.init()
    # opens the window with the size specifications given
    screen = pygame.display.set_mode(c.screenSize)
    # sets the font and size
    comicsansLargeFont = pygame.font.SysFont("comicsansms", 25)
    # set the font and size for the player key
    arialSmallFont = pygame.font.SysFont("Arial", 15)
    pygame.event.set_allowed(None)
    pygame.event.set_allowed([pygame.MOUSEBUTTONUP, pygame.MOUSEBUTTONDOWN, pygame.QUIT])
    # Create the Player Key
    playerKey = p.PlayerKey(arialSmallFont, playerList)
    boardSurface = screen.subsurface((0, 0), c.oceanSize)
    playerHandSurface = screen.subsurface((c.oceanWidth, 0), (c.gameMenuWidth, 225))
    playerHandSurface.fill(c.white)
    menuSurface = screen.subsurface((c.oceanWidth, 226), (c.gameMenuWidth, c.oceanHeight-226))
    menuSurface.fill(c.white)
    enemyInfoSurface = screen.subsurface((c.oceanWidth + c.gameMenuWidth + 1, 0), (c.gameEventLogWidth - 1, 225))
    enemyInfoSurface.fill(c.white)
    logSurface = screen.subsurface((c.oceanWidth + c.gameMenuWidth + 1, 226), (c.gameEventLogWidth - 1,
                                                                               c.oceanHeight - 226))
    logSurface.fill(c.white)

    # The pygame loop
    # A flag to track if the board has been drawn
    boardDrawn = False
    # A flag to track if the players have built their starting settlements and roads
    initialSettlementsBuilt = False
    # A flag to track if a player has won the game
    gameOver = False
    while 1:
        # Draw the key, hexes, odds tiles, and Robber
        if not boardDrawn:
            # Set the background color
            boardSurface.fill(c.oceanBlue)
            # Draw the player key
            playerKey.draw(boardSurface)
            # Loop through the hexes, so that they can be drawn
            for hexTile in hexes:
                # Draw the hex
                pygame.draw.polygon(boardSurface, hexTile.color, hexTile.vertexCoordinates, 0)
                # Check that the hex is not the desert hex
                if hexTile.resource != c.desert:
                    # Record the hex's odds tile
                    resourceOdds = str(hexTile.odds)
                    # Set the color of the odds number's text based on the value
                    if resourceOdds == "6" or resourceOdds == "8":
                        label = comicsansLargeFont.render(resourceOdds, 1, c.red)
                    else:
                        label = comicsansLargeFont.render(resourceOdds, 1, c.black)
                    # Place the number on the screen
                    boardSurface.blit(label, hexTile.coordinates)
            # Draw the Robber
            robber.draw_robber(boardSurface)
            # Draw the ports, colored according to their resource
            for port in ports:
                portColor = (0, 0, 0)
                if port.resources != c.resourceTypes:
                    portColor = c.resourceToColor[port.resources[0]]
                port.draw_port(boardSurface, portColor)
            # Draw any existing player objects
            for player in playerList:
                if player.builtRoads:
                    for road in player.builtRoads:
                        road.draw_road(boardSurface)
                if player.builtSettlements:
                    for settlement in player.builtSettlements:
                        settlement.draw_settlement(boardSurface)
            # Update the whole screen in order to show the newly drawn board
            pygame.display.flip()
            # Record that the board has been drawn
            boardDrawn = True

        # Set up the initial settlements and roads for each player
        if not initialSettlementsBuilt:
            print("Each player must build their first settlements and roads.")
            # Loop through the shuffled player list forwards once and then backwards once
            # playerList[::-1]:  TODO NEED TO CHANGE BACK!!!
            for player in playerList:
                # A flag to track whether the player has completed a valid action
                validAction = False
                # Give a line break
                print("")
                while not validAction:
                    print("For the settlement:")
                    buildResult = build_settlement(player, vertices, resourceDecks, boardSurface, playerKey)
                    if buildResult[0] == 0:
                        validAction = True
                        pygame.display.update()
                validAction = False
                # Repeat until the player successfully builds a road
                while not validAction:
                    print("For the road from that settlement:")
                    buildResult = build_road(player, vertices, longestRoad, resourceDecks, boardSurface, playerKey)
                    if buildResult[0] == 0:
                        validAction = True
                        pygame.display.update()
            # Record that the players have built the initial 2 settlements and roads
            initialSettlementsBuilt = True

        if not gameOver:
            # Loop through the players to let each take their game turns
            for player in playerList:
                print("\n{}, it is now your turn.".format(player.name))

                startTurn = None
                while startTurn is None:
                    startTurn = ui.present_menu(player, c.startMenu, "Ready?", menuSurface, comicsansLargeFont,
                                                arialSmallFont)
                if not startTurn:
                    sys.exit(0)

                player.count_points()
                draw_player_hand(player, playerHandSurface, comicsansLargeFont, arialSmallFont)
                pygame.display.update(playerHandSurface.get_rect())
                draw_enemy_info(player, playerList, enemyInfoSurface, arialSmallFont)
                pygame.display.update(enemyInfoSurface.get_rect())

                # Initiate the pre-harvest menu
                actionChoice = ui.present_menu(player, c.preHarvestMenu, "Pre-Harvest", menuSurface, comicsansLargeFont,
                                               arialSmallFont)
                result = eval(actionChoice)
                if not isinstance(result, int):
                    player.count_points()
                    draw_player_hand(player, playerHandSurface, comicsansLargeFont, arialSmallFont)
                    draw_enemy_info(player, playerList, enemyInfoSurface, arialSmallFont)
                    result = roll_dice(player)
                diceResult = result

                # Check if the roll was a 7, and have the players discards cards and play the Robber if so
                if diceResult == 7:
                    # Discard cards for players with more than 7
                    for playerToCheck in playerList:
                        if sum(playerToCheck.cardsInHand.values()) > 7:
                            halve_player_hand(playerToCheck, playerList, resourceDecks, playerHandSurface, menuSurface,
                                              enemyInfoSurface, comicsansLargeFont, arialSmallFont)
                            draw_enemy_info(player, playerList, enemyInfoSurface, arialSmallFont)
                    playMade = False
                    while not playMade:
                        # Have the player make a play with the Robber
                        robberPlay = use_robber(player, robber, hexes, boardSurface, playerKey, menuSurface,
                                                comicsansLargeFont, arialSmallFont)
                        if robberPlay[0] == 0:
                            playMade = True
                    # Update the screen to show the new location of the Robber
                    pygame.display.update()
                    # Print the result of the player stealing from someone
                    print(robberPlay[1])
                else:
                    # Have the players draw their resource cards
                    for playerDrawing in playerList:
                        for settlement in playerDrawing.builtSettlements:
                            playerDrawing.draw_resources(settlement.find_yield(diceResult), resourceDecks)
                        print("{} has {}".format(playerDrawing.name, playerDrawing.cardsInHand))
                    print("The decks have {}".format(resourceDecks))

                turnOver = False
                while not turnOver:
                    draw_player_hand(player, playerHandSurface, comicsansLargeFont, arialSmallFont)
                    draw_enemy_info(player, playerList, enemyInfoSurface, arialSmallFont)
                    pygame.display.update(playerHandSurface.get_rect())
                    actionChoice2 = ui.present_menu(player, c.postHarvestMenu, "Post-Harvest", menuSurface,
                                                    comicsansLargeFont, arialSmallFont)
                    result = eval(actionChoice2)
                    player.count_points()
                    print(result[1])
                    if result[1] == "Turn is over.":
                        turnOver = True
                        if result[2] >= 10:
                            print("\n{} has won the game with {} points!!".format(player.name, result[3]))
                            gameOver = True
                if gameOver:
                    break

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()