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 __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()
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
def board(self): board = Board() board.initialize_board(cities=CITIES_DATA) return board
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
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
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])
def board(self) -> Board: board = Board() board.initialize_board(cities=CITIES_DATA[:10]) return board