Esempio n. 1
0
    def start_game(self):
        self.board = Board()
        self.board.initialize_board()

        self.cures = [False] * 4

        self.lost = False

        self.infection_deck = InfectionDeck()
        self.infection_deck.init_infection()
        self.infection_deck.shuffle()

        for i in range(3):
            for j in range(3):
                card = self.infection_deck.draw_card()
                self.board.locations[card.city.id_].infect(amount=(3 - i))
                print(str(self.board.locations[card.city.id_].infections))

        infections = [location.infections for location in self.board.locations]
        infections_zip = list(zip(*infections))
        self.infection_sum = list(map(sum, infections_zip))

        self.player_deck = PlayerDeck(self.difficulty + 2)
        self.player_deck.init_player_deck()
        self.player_deck.shuffle()
        self.outbreaks = 0

        roles = list(Player.ROLES.keys())

        shuffle(roles)
        self.players = list()
        for j in range(self.num_players):
            role = roles.pop()
            player = Player(j, role, self.board)
            for j in range(2):
                player.add_card(self.player_deck.draw_card())
            self.players.append(player)

        self.player_deck.add_epidemics()

        self.turn_of = 0
        self.remaining_actions = 4
        max_pop = 0
        for player in self.players:
            for card in player.cards:
                if card.city.population > max_pop:
                    self.turn_of = player.id_
                    max_pop = card.city.population
Esempio n. 2
0
    def __init__(self, game_id):
        # choose pygame vs js frontend
        # IMPORTANT: if you update, also update imports in spell.py
        self.mode = 'js'  # 'js' or 'pygame'

        self.game_id = game_id
        self.screen_input = js_input if self.mode == 'js' else pygame_input
        self.screen = MockScreen() if self.mode == 'js' else PygameScreen()
        self.old_board = Board(self.screen)
        self.current_board = copy.deepcopy(self.old_board)
        self.start_action = 'place rooms'

        self.created = Game.current_time_str()
        self.updated = Game.current_time_str()
Esempio n. 3
0
    def from_hash(hash):
        game = Game(hash['game_id'])
        hash['screen'] = game.screen

        # TODO: make it work to save games that are still in setup steps
        # This would require saving start action and moving screen.choices to use indices.
        game.start_action = hash[
            'start_action'] if 'start_action' in hash else 'none'
        game.created = hash['created']
        game.updated = hash['updated']

        board = Board.from_hash(hash)
        game.current_board = board
        game.sync_boards()

        return game
Esempio n. 4
0
 def board(self):
     board = Board()
     board.initialize_board(cities=CITIES_DATA)
     return board
Esempio n. 5
0
class Controller:
    def __init__(self,
                 num_players: int = 2,
                 difficulty: int = 0,
                 board: Board = None,
                 cures: list = [False] * 4,
                 lost: bool = False,
                 infection_deck: InfectionDeck = None,
                 infection_sum: list = [0] * 4,
                 player_deck: PlayerDeck = None,
                 outbreaks: int = 0,
                 players: list = [],
                 turn_of: int = None,
                 remaining_actions: int = 4,
                 discard: int = 0):
        self.board = board
        self.cures = cures
        self.lost = lost
        self.infection_deck = infection_deck
        self.infection_sum = infection_sum
        self.player_deck = player_deck
        self.outbreaks = outbreaks
        self.players = players
        self.turn_of = turn_of
        self.remaining_actions = remaining_actions
        self.difficulty = difficulty
        self.num_players = num_players
        self.discard = discard

    def start_game(self):
        self.board = Board()
        self.board.initialize_board()

        self.cures = [False] * 4

        self.lost = False

        self.infection_deck = InfectionDeck()
        self.infection_deck.init_infection()
        self.infection_deck.shuffle()

        for i in range(3):
            for j in range(3):
                card = self.infection_deck.draw_card()
                self.board.locations[card.city.id_].infect(amount=(3 - i))
                print(str(self.board.locations[card.city.id_].infections))

        infections = [location.infections for location in self.board.locations]
        infections_zip = list(zip(*infections))
        self.infection_sum = list(map(sum, infections_zip))

        self.player_deck = PlayerDeck(self.difficulty + 2)
        self.player_deck.init_player_deck()
        self.player_deck.shuffle()
        self.outbreaks = 0

        roles = list(Player.ROLES.keys())

        shuffle(roles)
        self.players = list()
        for j in range(self.num_players):
            role = roles.pop()
            player = Player(j, role, self.board)
            for j in range(2):
                player.add_card(self.player_deck.draw_card())
            self.players.append(player)

        self.player_deck.add_epidemics()

        self.turn_of = 0
        self.remaining_actions = 4
        max_pop = 0
        for player in self.players:
            for card in player.cards:
                if card.city.population > max_pop:
                    self.turn_of = player.id_
                    max_pop = card.city.population

    def play_action(self, action: dict):
        player = self.players[self.turn_of]
        if self.discard > 0 and action.get('type') != 'discard':
            raise ValueError("Can only discard now!")
        if action.get('type') == 'move':
            self.move_player(int(action['data']), player)
        elif action.get('type') == 'heal':
            player.location.heal(
                player.role == 1 or self.cures[int(action.get('data'))],
                int(action.get('data')) if action.get('data') != '' else None)
            infections = [
                location.infections for location in self.board.locations
            ]
            infections_zip = list(zip(*infections))
            self.infection_sum = list(map(sum, infections_zip))
        elif action.get('type') == 'travel':
            self.travel_player(int(action['data']), player)
        elif action.get('type') == 'skip':
            return self.end_round()
        elif action.get('type') == 'build':
            self.build(player)
        elif action.get('type') == 'cure':
            self.cure(int(action['data']), player)
        elif action.get('type') == 'discard':
            self.discard_action(int(action['data']), player)
            return self.end_round(action.get('type') == 'discard')

        self.remaining_actions -= 1
        if self.remaining_actions == 0:
            self.end_round()

    def build(self, player):
        if player.location.name not in [card.city.name for card in player.cards
                                        if card.city is not None] \
                and player.role != 4:
            raise ValueError("City card not available")
        if player.role != 4:
            action_cards = [card for card in player.cards if card.city is None]
            location_cards = [
                card for card in player.cards if card.city is not None
            ]
            player.cards = [
                card for card in location_cards
                if card.city.id != player.location.id
            ] + action_cards
        self.board.add_research_center(player.location.id)

    def cure(self, color, player):
        amount_to_cure = 5 if player.role != 5 else 4
        location_cards = [
            card for card in player.cards if card.city is not None
        ]
        action_cards = [card for card in player.cards if card.city is None]
        cards_to_cure = [
            card for card in location_cards if card.city.color == color
        ]
        if len(cards_to_cure) < amount_to_cure:
            raise ValueError("Not enough cards to cure")
        while len(cards_to_cure) > amount_to_cure:
            cards_to_cure.pop(0)
        location_cards = [
            card for card in location_cards if card not in cards_to_cure
        ]
        player.cards = location_cards + action_cards
        self.cures[color] = True

    def discard_action(self, card_id, player):
        player.cards = [card for card in player.cards if card.id != card_id]
        self.discard -= 1

    def end_round(self, skip_player: bool = False):
        if not skip_player:
            if not self.player_card_stage(self.turn_of):
                self.lost = True

        if len(self.players[self.turn_of].cards) > 7:
            self.discard = len(self.players[self.turn_of].cards) - 7
            return

        self.infection_stage()
        if self.outbreaks > 7:
            self.lost = True

        infections = [location.infections for location in self.board.locations]
        infections_zip = list(zip(*infections))
        self.infection_sum = list(map(sum, infections_zip))
        if max(self.infection_sum) > 24:
            self.lost = True

        if self.lost:
            self.turn_of = None
            return

        self.board.unlock_cities()

        self.turn_of += 1
        if self.turn_of == len(self.players):
            self.turn_of = 0
        self.remaining_actions = 4

    def player_card_stage(self, player_id: int) -> bool:
        for i in range(2):
            drawn_card = self.player_deck.draw_card()
            if drawn_card is None:
                return False
            if drawn_card.action == "Epidemic":
                print("Epidemic")
                self.epidemic()
            else:
                self.players[player_id].add_card(drawn_card)
        return True

    def epidemic(self):
        # Speed up
        self.board.current_speed += 1

        # Infect
        card = self.infection_deck.draw_last()
        self.outbreaks += self.board.infect(card.city.id_, 3)

        # Return drawn
        self.infection_deck.return_drawn()

    def infection_stage(self):
        forbiden = list()
        connections = [
            player.location.connections for player in self.players
            if player.role == 2
        ]
        forbiden = [city.id for city in connections] + [
            player.location for player in self.players if player.role == 2
        ]
        cities = list()
        for i in range(self.board.infection_speeds[self.board.current_speed]):
            card = self.infection_deck.draw_card()

            if card is not None:
                if card.city.id_ not in forbiden:
                    self.outbreaks += self.board.infect(card.city.id_)
                    cities.append(self.board.locations[card.city.id_])
            else:
                return cities
        return cities

    def move_player(self, destination, player):
        if self.board.locations[destination] not in player.possible_moves():
            raise ValueError("City not available to move")
        player.move(self.board.locations[destination])

    def travel_player(self, destination, player):
        if self.board.locations[destination].name not in [
                city.name for city in player.possible_travel_to()
        ]:
            raise ValueError("City not available to travel")
        player.cards = [
            card for card in player.cards if card.city.id != destination
        ]
        player.move(self.board.locations[destination])

    def serialize(self):
        serial = self.board.serialize()
        serial.update({
            'players': [player.serialize() for player in self.players],
            'outbreaks':
            self.outbreaks,
            'cures': {COLORS[i]: self.cures[i]
                      for i in range(4)},
            'turn': {
                'player': self.turn_of,
                'remaining_actions': self.remaining_actions
            },
            'infections_sum':
            self.infection_sum,
            'infection_deck':
            self.infection_deck.serialize(),
            'player_deck':
            self.player_deck.serialize(),
            'lost':
            self.lost,
            'discard':
            self.discard
        })
        return serial
Esempio n. 6
0
 def test_deserialize(self, serialized):
     board = Board()
     board.initialize_board(cities=CITIES_DATA[:2])
     board.infect(0, 2)
     board.infect(0, 2)
     assert Board.deserialize(serialized) == board
Esempio n. 7
0
 def test_init(self):
     board = Board()
     assume(board.locations == [])
     assume(board.research_centers == [])
     assume(board.current_speed == 0)
     assume(board.infection_speeds == [2, 2, 2, 3, 3, 4, 4])
Esempio n. 8
0
 def board(self) -> Board:
     board = Board()
     board.initialize_board(cities=CITIES_DATA[:10])
     return board