from .harbor import Harbor, HarborType from .player import Player from .statuses import Statuses from .building import Building from .tile_type import TileType from .card import ResCard, DevCard from .tile import Tile from .point import Point # used to shuffle the deck of tiles import random import abc # used for debugging import pprint # Base class for different Catan boards # Should not be instantiated, otherwise the board will be empty class Board(object): __metaclass__ = abc.ABCMeta def __init__(self, game): # The game the board is in self.game = game # The tiles on the board # Should be set in a subclass self.tiles = () # The points on the board # Where the players can place settlements/cities # Will be set at the end of __init__ self.points = () # The roads self.roads = [] # The locations of the harbors self.harbors = [] # The location of the robber # going r, i self.robber = None # gives the players cards for a certain roll def add_yield(self, roll): # Track resources distributed: {player_name: [resource_names]} distribution = {} for r in self.points: for p in r: # Check there is a building on the point if p.building != None: building = p.building tiles = p.tiles # checks if any tiles have the right number for current_tile in tiles: # makes sure the robber isn't there if self.robber == current_tile.position: # skips this tile continue if current_tile.token_num == roll: # adds the card to the player's inventory owner = building.owner # gets the card type card_type = Board.get_card_from_tile(current_tile.type) if card_type: cards_to_add = [] # adds two if it is a city if building.type == Building.BUILDING_CITY: cards_to_add = [card_type, card_type] else: cards_to_add = [card_type] self.game.players[owner].add_cards(cards_to_add) # Record distribution player_name = f"Player {owner + 1}" if player_name not in distribution: distribution[player_name] = [] for card in cards_to_add: distribution[player_name].append(card.name.split('.')[-1] if hasattr(card, 'name') else str(card)) return distribution # adds a Building object to the board def add_building(self, building, point): point.building = building # adds a Building object, which must be a road # since roads record their own position and are not in self.points def add_road(self, road): self.roads.append(road) # upgrades an existing settlement to a city def upgrade_settlement(self, player, point): # Get building at point building = point.building # checks there is a settlement at r, i if building == None: return Statuses.ERR_NOT_EXIST # checks the settlement is controlled by the correct player # if no player is specified, uses the current controlling player if building.owner != player: return Statuses.ERR_BAD_OWNER # checks it is a settlement and not a city if building.type != Building.BUILDING_SETTLEMENT: return Statuses.ERR_UPGRADE_CITY # checks the player has the cards needed_cards = [ ResCard.Wheat, ResCard.Wheat, ResCard.Ore, ResCard.Ore, ResCard.Ore ] if not self.game.players[player].has_cards(needed_cards): return Statuses.ERR_CARDS # removes the cards self.game.players[player].remove_cards(needed_cards) # changes the settlement to a city building.type = Building.BUILDING_CITY # adds another victory point self.game.players[player].victory_points += 1 return Statuses.ALL_GOOD # gets all the buildings on the board def get_buildings(self): buildings = [] for r in self.points: for p in r: if p.building != None: buildings.append(p.building) return buildings # moves the robber to a givne coord def move_robber(self, tile_pos): self.robber = tile_pos def __repr__(self): return ("Board Object") # Get a shuffled deck of the correct number of each type of tile in a board @staticmethod def get_shuffled_tile_deck(): deck = [] # sets up all_tiles for i in range(4): # adds four fields, forests and pastures deck.append(TileType.Fields) deck.append(TileType.Forest) deck.append(TileType.Pasture) # adds three mountains and hills if i < 3: deck.append(TileType.Mountains) deck.append(TileType.Hills) # adds one desert if i == 0: deck.append(TileType.Desert) # shuffles the deck random.shuffle(deck) return deck @staticmethod def get_shuffled_tile_nums(): nums = [] # Get 2 of each number, most of the time for i in range(2): # Go through each type for x in range(2, 13): # Does not add a number token with 7 if x != 7: # Only adds one 2 and one 12 if x == 2 or x == 12: if i == 0: nums.append(x) # Adds two of everything else else: nums.append(x) random.shuffle(nums) return nums # returns the card associated with the tile # for example, Brick for Hills, Wood for forests, etc @staticmethod def get_card_from_tile(tile): # returns the appropriete card if tile == TileType.Forest: return ResCard.Wood elif tile == TileType.Hills: return ResCard.Brick elif tile == TileType.Pasture: return ResCard.Sheep elif tile == TileType.Fields: return ResCard.Wheat elif tile == TileType.Mountains: return ResCard.Ore else: return None