def __init__(self):
        self.players = []
        for i in [0, 1]:
            self.players.append(TwentyFourPlayer())

        self.trick = Trick()

        self.deck = TwentyFourDeck()
        self.deck.shuffle()
        self.deal(20)

        self.timeout = 10       # lower timeout implies higher difficulty
class TwentyFourTable(Table):
    def __init__(self):
        self.players = []
        for i in [0, 1]:
            self.players.append(TwentyFourPlayer())

        self.trick = Trick()

        self.deck = TwentyFourDeck()
        self.deck.shuffle()
        self.deal(20)

        self.timeout = 10       # lower timeout implies higher difficulty

    def play_game(self):
        def timeout_handler(signum, frame):
            raise TimeoutException()

        while not self.winner():
            if len(self.trick.cards) == 0:
                self.play_round()

            if not self.find_solution():
                self.return_cards()
                continue

            for i in [0, 1]:
                print(_('Player {} has {} cards and {} points.').format(i, len(self.players[i].hand), self.players[i].points))

            print(_('Make 24 out of these cards:'))
            print('   {}'.format(self.trick.cards))

            print(_('Press any key to buzz in...'))

            if os.name == 'nt':
                start_time = time.time()
                while True:
                    if msvcrt.kbhit():
                        print(_('Human player buzzed in!'))
                        self.buzz_in(0)
                        break
                    else:
                        if time.time() - start_time > self.timeout:
                            print(_('Computer player buzzed in!'))
                            self.buzz_in(1)
                            break
            else:
                rlist, __, __ = select([sys.stdin], [], [], self.timeout)
                if rlist:
                    sys.stdin.readline()
                    print(_('Human player buzzed in!'))
                    self.buzz_in(0)
                else:
                    print(_('Computer player buzzed in!'))
                    self.buzz_in(1)

            # shouldn't happen with new buzzing system, but just in case...
            if self.buzzed_in != 0 and self.buzzed_in != 1:
                print(_('Invalid input.'))
                continue

            if self.buzzed_in == 0:
                print(_('What is your guess?'))
                guess = raw_input('> ')

                if not self.is_valid_guess(guess):
                    print(_('Guess is invalid!'))
                    continue

                if not self.is_correct_guess(guess):
                    print(_('That doesn\'t make 24!'))
                    continue
            elif self.buzzed_in == 1:
                print(_('The computer guessed {}.').format(self.find_solution()))

            # print(_('Player {} is correct!').format(self.buzzed_in))
            self.solve(self.buzzed_in)
            print('')
        print(_('Player {} has won!').format(self.winner()))

    def play_round(self):
        self.trick.cards.append(self.players[0].hand.pop())
        self.trick.cards.append(self.players[0].hand.pop())
        self.trick.cards.append(self.players[1].hand.pop())
        self.trick.cards.append(self.players[1].hand.pop())

    def return_cards(self):
        print(_("Couldn't find a solution to current trick. Returning cards to players' hands..."))
        self.players[0].hand.insert(0, self.trick.cards[0])
        self.players[0].hand.insert(0, self.trick.cards[1])
        self.players[1].hand.insert(0, self.trick.cards[2])
        self.players[1].hand.insert(0, self.trick.cards[3])
        self.trick = Trick()

    def buzz_in(self, player_num):
        self.buzzed_in = player_num

    # Test for syntactical correctness.
    # FIXME: Some valid formulae are throwing false negatives.
    def is_valid_guess(self, guess):
        is_valid = True

        try:
            ast = compiler.parse(guess)
        except SyntaxError:
            is_valid = False
        return is_valid

    # Test for legal usage of cards.
    # Fails if guess does not use each number in the trick exactly once.
    # Fails if guess uses an illegal operator (legal operators are +, -, *, /, (, and ).
    def is_legal_guess(self, guess):
        guess_numbers = []
        trick_numbers = map(lambda card: str(card.value), self.trick.cards)
        valid_operators = ['+', '-', '*', '/', '(', ')']

        for c in guess:
            if c.isdigit():
                # print "Adding {} to list of numbers.".format(c)
                guess_numbers.append(c)
            elif c in valid_operators:
                # print "Skipping over operator {}.".format(c)
                continue
            elif c.isspace():
                # print "Skipping over a space."
                continue
            else:
                # print "Found invalid character {}!".format(c)
                return False

        if sorted(guess_numbers) != sorted(trick_numbers):
            # print "Mismatched numbers!"
            return False

        return True

    def is_correct_guess(self, guess):
        return eval(guess) == 24

    # FIXME: eliminate integer division from solutions.
    def find_solution(self):
        for c in itertools.permutations(self.trick.cards):
            for o in itertools.permutations(["+", "-", "*", "/"]):
                guess = str(c[0].value)
                for i in range(3):
                    guess += o[i] + str(c[i+1].value)
                if eval(guess) == 24:
                    return guess
        return False

    def solve(self, player_num):
        self.players[player_num].hand.extend(self.trick.cards)
        self.trick.cards = []
        self.players[player_num].points += 1

    def winner(self):
        if len(self.players[0].hand) == 40 or self.players[0].points == 15:
            return 0
        if len(self.players[1].hand) == 40 or self.players[1].points == 15:
            return 1
        return False