예제 #1
0
def create_new_game():
    """
	Receive the form to create a new game
	-> create the game (ie runPhase it)
	"""
    # get Players
    player1 = RegularPlayer.getFromName(request.forms.get('player1'))
    player2 = RegularPlayer.getFromName(request.forms.get('player2'))

    # !TODO: add some options (timeout, seed, etc.) in the html, and send them to the constructor
    try:
        # the constructor will check if player1 and player2 are available to play
        # no need to store the game object created here
        Game.getTheGameClass()(player1, player2)

    except ValueError as e:
        # !TODO: redirect to an error page
        # TODO: log this
        return 'Error. Impossible to create a game with ' + str(
            request.forms.get('player1')) + ' and ' + str(
                request.forms.get('player2')) + ': "' + str(e) + '"'
    else:
        redirect('/')
예제 #2
0
    def waitForGame(self):
        """
		Waits for a message "WAIT_GAME %s" and then wait for a game (with an Event)
		%s is a string like (options is like "key1=value1 key2=value2 ...")
		- "{options}": regular game (with options)
		- "TOURNAMENT NAME {options}": tournament
		- or "NAME {options}": play agains training player
        Returns nothing
		"""
        # !TODO: normalize the options: should be "[options]", "TRAINING <name> [options]" or "TOURNAMENT <name> [options]"
        # get the WAIT_GAME message
        data = self.receiveData()
        if not data.startswith("WAIT_GAME"):
            self.sendData("Bad protocol, should send 'WAIT_GAME %s' command")
            raise ProtocolError(
                "Bad protocol, should send 'WAIT_GAME %s' command")

        # parse the game type (in the form "TOURNAMENT NAME key1=value1..." or "NAME key1=value1 key2=value2")
        trainingPlayerName = ""
        tournamentName = ""
        options = {}
        try:
            terms = shlex.split(data[10:])
            if terms:
                if "=" in terms[0]:
                    trainingPlayerName = ""
                    tournamentName = ""
                    options = dict([token.split('=') for token in terms])
                elif terms[0] == 'TOURNAMENT':
                    trainingPlayerName = ""
                    tournamentName = terms[1]
                    options = dict([token.split('=') for token in terms[2:]])
                else:
                    trainingPlayerName = terms[0]
                    tournamentName = ""
                    options = dict([token.split('=') for token in terms[1:]])
        except ValueError:
            strerr = "The string sent with 'WAIT_GAME' is not valid (should be '{options}'," \
                     " 'NAME {options}' or 'TOURNAMENT NAME {options}', but is '%s' instead)"
            self.sendData(strerr)
            raise ProtocolError(strerr)

        if trainingPlayerName:
            # Create a particular Game
            try:
                # create game (no need to store it in a variable)
                g = Game.getTheGameClass().gameFactory(trainingPlayerName,
                                                       self._player, options)
            except ValueError as err:
                self.sendData(
                    "The training player sent by '%s' command is not valid (%s)"
                    % (data, err))
                raise ProtocolError(
                    "The training player sent by '%s' command is not valid (%s)"
                    % (data, err))
            # log it
            self.logger.debug(
                "The game %s starts with training player `%s` and options=%s" %
                (g.name, trainingPlayerName, options))
        elif tournamentName:
            try:
                # register the player in the tournament
                Tournament.registerPlayer(self._player, tournamentName)
            except ValueError as err:
                self.sendData("The tournament '%s' cannot be joined: %s" %
                              (tournamentName, err))
                raise ProtocolError(
                    "The tournament '%s' cannot be joined: %s" %
                    (tournamentName, err))

        # just send back OK
        self.sendData("OK")

        # wait for the Game
        # and send every second a "NOT_READY" if the game do not start
        # in order to know if the client has disconnected
        gameHasStarted = self._player.waitForGame(5)
        while not gameHasStarted:
            self.sendData("NOT_READY")
            gameHasStarted = self._player.waitForGame(3)

        # now send the game name
        self.sendData(self.game.name)

        # now send the game sizes
        self.sendData(self.game.getDataSize())
    def runPhase(self, **kwargs):
        """Launch a phase of the tournament
		"""
        # check if a phase is not already running
        if self.isPhaseRunning:
            # do noting, since a phase is already running
            return

        # first launch ?
        if not self.hasBegan:
            # we first need to get the list of 2-tuple (player1's name, player2's name)
            # of players who will play together in the phase
            try:
                phase, self._matches = next(self._matchGen)
            except StopIteration:
                self.endTournament()
            else:
                self.newPhase(phase)
        else:
            # otherwise, start a new phase
            self.newPhase()

        # build the dictionary of the games (pair of players' name -> list of score (tuple) and current game
        # (we remove fake players with "" as name)
        self._games = {(pName1, pName2): [[0, 0], None]
                       for pName1, pName2 in self._matches
                       if pName1 and pName2}
        # run the games
        for self._round in range(1, 2 * self.nbRounds4Victory + 1):

            for (pName1, pName2), (score, _) in self._games.items():

                if max(score) < self.nbRounds4Victory:
                    # choose who starts (-1 for random, ie for the last round)
                    start = (
                        self._round - 1
                    ) % 2 if self._round < 2 * self.nbRounds4Victory else -1

                    # run the game only if the two players are here (otherwise, one wins directly)
                    player1, player2 = self._players[pName1], self._players[
                        pName2]
                    if player1 and player2:

                        self._games[(pName1,
                                     pName2)][1] = Game.getTheGameClass()(
                                         player1,
                                         player2,
                                         start=start,
                                         tournament=self,
                                         **kwargs)
                        self.logger.info("The game `%s` vs `%s` starts",
                                         pName1, pName2)
                        self._queue.put_nowait(None)
                    else:
                        # one player is not playing anymore (disconnected), so the other wins
                        score = self._games[(pName1, pName2)][0]
                        if player1 is not None:
                            score[0] += 1
                        elif player2 is not None:
                            score[1] += 1
                        else:
                            # in the case where the 2 players are disconnected, the 1st win...
                            # !FIXME: introduce equality (the result of a game is either WIN, LOOSE or EQUALITY !)
                            score[start] += 1

            # update the websockets (no need to update everytime a game is added)
            self.sendUpdateToWebSocket()
            # and wait for all the games to end (before running the next round)
            self._queue.join()
            time.sleep(
                1
            )  # !!TODO: check why is not fully working when we remove this sleep....

        # update the scores
        self.updateScore()

        # Prepare the next list of 2-tuple (player1,player2) of players who will play in next phase
        try:
            phase, self._matches = next(self._matchGen)
        except StopIteration:
            # no more matches to run (end of the tournament)
            self.endTournament()
        else:
            self.endPhase(phase)

        # update data through websockets
        self.sendUpdateToWebSocket()