Exemple #1
0
 def __init__(self):
     super(GameController, self).__init__()
     self.players = []
     self.state = GameState()
     self.shutdown_event = threading.Event()
     self.id = None
     self.lock_start = threading.Lock()
Exemple #2
0
 def _reset(self):
     """
     Reset the game.
     """
     logging.info('Resetting')
     self._stop_players()
     self.players = []
     self.state = GameState()
Exemple #3
0
def parse_header(header):
    game_state = GameState()
    base_featureset = FeatureSet()

    for line in header.split("\n"):
        line = line.strip()
        if line.startswith("info,"):
            try:
                _, key, value = csv_split(line)
            except Exception:
                logging.error("Choked on line: %s" % line)
                raise

            if key in ["visteam", "hometeam"]:
                setattr(GameState, key, value)

            fs_key = "game_%s" % key
            if fs_key in FeatureSet.__slots__:
                setattr(FeatureSet, fs_key, value)

    return game_state, base_featureset
Exemple #4
0
class XMLRPCCliPlayer(players.CliPlayer):
    """
    XML-RPC command line interface human player.
    """
    def __init__(self, player_name):
        players.CliPlayer.__init__(self, player_name)
        self.game_state = GameState()
        self.hand = None

    def handle_event(self, event):
        if isinstance(event, CardPlayedEvent):
            self.card_played(event.player, event.card, event.game_state)
        elif isinstance(event, MessageEvent):
            self.send_message(event.sender, event.message)
        elif isinstance(event, TrickPlayedEvent):
            self.trick_played(event.player, event.game_state)
        elif isinstance(event, TurnEvent):
            self.game_state.update(event.game_state)
            state = self.controller.get_state(self.id)
            self.hand = state['hand']
            self.game_state.update(state['game_state'])
        elif isinstance(event, StateChangedEvent):
            self.game_state.update(event.game_state)
        else:
            print "unknown event: %s" % event

    def wait_for_turn(self):
        """
        Wait for this player's turn.
        """
        while True:

            time.sleep(0.5)

            if self.controller is not None:
                events = self.controller.get_events(self.id)
                for event in events:
                    self.handle_event(event)

            if self.game_state.turn_id == self.id:
                break
Exemple #5
0
def main():
    input_queue = queue.Queue()

    input_thread = threading.Thread(target=add_input, args=(input_queue, ))
    input_thread.daemon = True
    input_thread.start()

    outs, ins = [], []

    turn = 0
    total_turns = 0
    prev_turn = -1

    pygame.key.set_repeat(500, 30)

    if len(sys.argv) > 1 and sys.argv[1] == '-s':
        d = os.path.dirname(os.path.realpath(__file__))
        fname = os.path.join(d, "logs", "commands_{:.0f}".format(time.time()))
        cf = open(fname, "w")
    else:
        cf = None

    global sz
    while True:
        while not input_queue.empty():
            line = input_queue.get()
            if line.startswith("->"):
                if cf is not None:
                    cf.write(line)
                outs.append(parse_line(line[3:].strip()))
            if line.startswith("<-"):
                if cf is not None:
                    cf.write(line)
                ins.append(parse_line(line[3:].strip()))

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

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    sz += 1
                if event.key == pygame.K_2 and sz > 1:
                    sz -= 1
                if event.key == pygame.K_o:
                    if turn > 1:
                        turn -= 1
                if event.key == pygame.K_p:
                    if turn + 1 < total_turns:
                        turn += 1

        total_turns = min(len(ins), len(outs))
        if total_turns == 0:
            continue

        try:
            gs = GameState(ins[turn])
        except:
            if turn == 0 and total_turns > 1:
                turn += 1
                gs = GameState(ins[turn])

        screen.fill(0)
        if turn != prev_turn:
            print("=" * 20)
            print("turn {}/{}".format(turn, total_turns))
            print("sent -> {}".format(outs[turn]))
            print("got  <- {}".format(ins[turn]))
            prev_turn = turn

        last_text_pos_y = 40
        for sh in gs.ships:
            if sh.player_type == gs.my_type:
                color = (0, 192, 0)
            else:
                color = (192, 0, 0)

            screen_pos = to_screen(sh.pos)
            if sh.player_type == DEFENDER_ID:
                pygame.draw.circle(screen, color, screen_pos, 15, 2)
            else:
                pygame.draw.rect(
                    screen, color,
                    (screen_pos[0] - 15, screen_pos[1] - 15, 30, 30), 2)
            pygame.draw.line(screen, color, screen_pos,
                             to_screen(sh.pos + sh.speed), 2)

            screen.blit(font.render(str(sh.ship_id), 1, color),
                        (screen_pos[0] - 35, screen_pos[1] - 12))
            screen.blit(
                small_font.render(
                    "{}+{}".format(sh.pos, sh.speed).replace(" ", ""), 1,
                    color), (screen_pos[0] + 20, screen_pos[1] - 6))

            text = '(id:{}, energy:{}, shoot_energy:{}, rest:{}, health:{}, tired:{}/{})'.format(
                sh.ship_id, sh.energy, sh.shoot_energy, sh.rest, sh.health,
                sh.tiredness, sh.tiredness_limit)

            for m in sh.prev_moves:
                text += "  " + str(m)
                if m.move_type == 2:
                    target_pos = to_screen(m.pos())
                    pygame.draw.line(screen, color, screen_pos, target_pos,
                                     1 + m.args[2] // 10)

            text_info = font_ship_info.render(text, 1, color)
            screen.blit(text_info, (10, last_text_pos_y))
            last_text_pos_y += 24

        border_color = (200, 200, 200)
        draw_centered_rect(border_color, gs.world_size, 2)
        draw_centered_rect(border_color, gs.planet_size, 0)  # fill

        tt = font.render(
            'turn {}/{}; sz = {}; finished = {}'.format(
                turn, total_turns, sz, gs.game_finished), 1, (192, 192, 192))
        # print(dir(tt.get_rect()))
        screen.blit(tt, (10, 5))

        pygame.display.update()
Exemple #6
0
 def __init__(self, player_name):
     players.CliPlayer.__init__(self, player_name)
     self.game_state = GameState()
     self.hand = None
Exemple #7
0
class GameController(object):
    """
    The controller class that runs everything.
    """

    def __init__(self):
        super(GameController, self).__init__()
        self.players = []
        self.state = GameState()
        self.shutdown_event = threading.Event()
        self.id = None
        self.lock_start = threading.Lock()

    def register_player(self, player):
        """
        Register a new Player.
        """
        if player.id in [pl.id for pl in self.players]:
            raise GameError('Player already registered to game')

        if len(self.players) == 4:
            raise GameError('Already 4 players registered')

        self.players.append(player)
        # TODO: should we generate UUIDs instead?
        if player.id == None:
            player.id = str(self.players.index(player))

        player.team = self.players.index(player) % 2

    def player_leave(self, player_id):
        """
        Player leaves the game.
        """
        self._send_msg('Player %s quit' % player_id)
        plr = self.get_player(player_id)
        if plr:
            self.players.remove(plr)
            plr.hand.clear()
            plr.stop() # stops the thread in case of ThreadedPlayer

        # reset the game unless we are still in OPEN state
        if self.state.state != GameState.OPEN:
            self._reset()

    def player_quit(self, player_id):
        """
        Leave and quit the game.
        """
        self.player_leave(player_id)
        self.shutdown_event.set()

    def get_player(self, player_id):
        """
        Get player by id.
        """
        for plr in self.players:
            if plr.id == player_id:
                return plr

        return None

    def _get_player_in_turn(self, turn):
        """
        Get player who is in turn.
        """
        if turn >= 0:
            return self.players[turn % 4]

        return None

    def _next_in_turn(self, thenext=None):
        """
        Set the next player in turn.
        """
        self.state.next_in_turn(thenext)
        self.state.turn_id = self._get_player_in_turn(self.state.turn).id

    def _set_state(self, new_state):
        """
        Change the game state.
        """
        self.state.state = new_state
        for player in self.players:
            player.state_changed(self.state)

    def _stop_players(self):
        """
        Stop all running players.
        """
        self._set_state(GameState.STOPPED)
        for player in self.players:
            if player:
                player.act(self, self.state)

        for player in self.players:
            if player and isinstance(player, players.ThreadedPlayer):
                if player.is_alive() and player.thread is not threading.current_thread():
                    player.join()

    def _reset(self):
        """
        Reset the game.
        """
        logging.info('Resetting')
        self._stop_players()
        self.players = []
        self.state = GameState()

    def _get_team_players(self, team):
        """
        Get players in a team.
        """
        return [player for player in self.players if player.team == team]
       
    def _get_team_str(self, team):
        """
        Get team string representation.
        """
        plrs = self._get_team_players(team)
        return '%d (%s)' % (team + 1, ', '.join([pl.player_name for pl in plrs]))

    def _send_msg(self, msg):
        """
        Send a message to all players.
        """
        logging.debug(msg)
        for player in self.players:
            player.send_message('', msg)

    @synchronized_method('lock_start')
    def start_game(self):
        """
        Start the game.
        """
        if self.state.state != GameState.OPEN:
            raise GameError('Game already started')

        if len(self.players) < 4:
            raise GameError('Not enough players')
        
        for player in self.players:
            player.start()

        self._start_new_hand()

    def wait_for_shutdown(self):
        """
        Wait for shutdown event and shut down after it.
        """
        self.shutdown_event.wait()
        self.shutdown()

    def _signal_act(self):
        """
        Tell the player who is in turn to act.
        """
        self._get_player_in_turn(self.state.turn).act(self, self.state)

    def _start_new_hand(self):
        """
        Start a new hand.
        """
        logging.info('New hand')
        self.state.tricks = [0, 0]

        # create a full deck
        deck = CardSet.new_full_deck()

        logging.debug('deck is %s', str(deck))
        deck.shuffle()
        logging.debug('shuffled deck %s', str(deck))

        deck.deal([player.hand for player in self.players])

        for player in self.players:
            player.hand.sort()
            logging.debug("%s's hand: %s", player.player_name,
                str(player.hand))

        # voting 
        self.state.mode = NOLO
        self.state.rami_chosen_by = None
        self._set_state(GameState.VOTING)

        # uncomment following to skip voting
        #self._set_state(GameState.ONGOING)
        # start the game
        self._next_in_turn(self.state.dealer + 1)
        self._signal_act()

    def _trick_played(self):
        """
        A trick (4 cards) has been played.
        """
        table = self.state.table
        high = table.get_cards(suit=table[0].suit).get_highest()
        high_played_by = self.get_player(high.played_by)
        team = high_played_by.team
        self._send_msg('Team %s takes this trick' % (self._get_team_str(team)))
        self.state.tricks[team] += 1
        self._send_msg('Tricks: %s' % self.state.tricks)
        # send signals
        for plr in self.players:
            plr.trick_played(high_played_by, self.state)

        self.state.table.clear()

        # do we have a winner?
        if self.state.tricks[0] + self.state.tricks[1] == 13:
            self._hand_played()
        else:
            self._next_in_turn(self.players.index(high_played_by))
            self._signal_act()

    def _hand_played(self):
        """
        A hand has been played.
        """

        if self.state.mode == NOLO:
            if self.state.tricks[0] < self.state.tricks[1]:
                winner = 0
                loser = 1
            else:
                winner = 1
                loser = 0
            score = (7 - self.state.tricks[winner]) * 4
        else: 
            if self.state.tricks[0] > self.state.tricks[1]:
                winner = 0
                loser = 1
            else:
                winner = 1
                loser = 0
            if self.state.rami_chosen_by.team != winner:
                self._send_msg("Double points for taking opponent's rami!")
                score = (self.state.tricks[winner] - 6) * 8
            else:
                score = (self.state.tricks[winner] - 6) * 4

        self._send_msg('Team %s won this hand with %d tricks' % 
                (self._get_team_str(winner), self.state.tricks[winner]))

        if self.state.score[loser] > 0:
            self._send_msg('Team %s fell down' % (self._get_team_str(loser)))
            self.state.score = [0, 0]
        else:
            self.state.score[winner] += score
            if self.state.score[winner] > 52:
                self._send_msg('Team %s won with score %d!' % 
                        (self._get_team_str(winner), self.state.score[winner]))
                self.shutdown_event.set()
                return
            else:
                self._send_msg('Team %s is at %d' % 
                        (self._get_team_str(winner), self.state.score[winner]))

        self.state.dealer = (self.state.dealer + 1) % 4
        self._start_new_hand()

    def shutdown(self):
        """
        Shutdown the game.
        """
        self._stop_players()
        sys.exit(0)

    def _vote_card(self, player, card):
        """
        Player votes with a card.
        """
        table = self.state.table

        card = copy.copy(card)
        card.played_by = player.id
        table.append(card)
        # fire signals
        for plr in self.players:
            plr.card_played(player, card, self.state)

        if card.suit == common.DIAMOND or card.suit == common.HEART:
            self.state.mode = RAMI
            self.state.rami_chosen_by = player
            self._next_in_turn(self.players.index(player) - 1)
            self._begin_game()
        elif len(table) == 4:
            self.state.mode = NOLO
            self._next_in_turn()
            self._begin_game()
        else:
            self._next_in_turn()

        self._signal_act()

    def _begin_game(self):
        if self.state.mode == RAMI:
            self._send_msg('Rami it is')
        else:
            self._send_msg('Nolo it is')

        self._send_msg('Game on, %s begins!' % self._get_player_in_turn(self.state.turn))

        self.state.table.clear()
        self._set_state(GameState.ONGOING)
            
    def play_card(self, player, card):
        """
        Play one card on the table.
        """
        if self._get_player_in_turn(self.state.turn).id != player.id:
            raise RuleError('Not your turn')

        table = self.state.table

        if self.state.state == GameState.VOTING:
            self._vote_card(player, card)

        elif self.state.state == GameState.ONGOING:
            # make sure that suit is followed
            if len(table) > 0 and card.suit != table[0].suit:
                if len(player.hand.get_cards(suit=table[0].suit)) > 0:
                    raise RuleError('Suit must be followed')
            
            # make sure that the player actually has the card
            try: 
                table.append(player.hand.take(card))
                card.played_by = player.id
            except ValueError:
                raise RuleError('Invalid card')

            if len(table) == 4:
                # TODO: there must be a better way for this
                turn_backup = self.state.turn
                self.state.turn = TURN_NONE
                # fire signals with temporary state
                # this is to let clients know that all four cards have been played
                # and it's nobody's turn yet
                for plr in self.players:
                    plr.card_played(player, card, self.state)

                self.state.turn = turn_backup
                self._trick_played()
            else:
                self._next_in_turn()
                # fire signals
                for plr in self.players:
                    plr.card_played(player, card, self.state)
                self._signal_act()