Пример #1
0
    def on_login(self, data: dict):
        if self.game is not None or self.player is not None:
            raise errors.BadCommand('You are already logged in')

        self.check_keys(data, ['name'])
        player_name = data['name']
        password = data.get('password', None)

        player = Player.get(player_name, password=password)
        if not player.check_password(password):
            raise errors.AccessDenied('Password mismatch')

        game_name = data.get('game', 'Game of {}'.format(player_name))
        num_players = data.get('num_players', CONFIG.DEFAULT_NUM_PLAYERS)
        num_turns = data.get('num_turns', CONFIG.DEFAULT_NUM_TURNS)

        game = Game.get(game_name,
                        num_players=num_players,
                        num_turns=num_turns)

        game.check_state(GameState.INIT, GameState.RUN)
        player = game.add_player(player)
        self.game = game
        self.game_idx = game.game_idx
        self.player = player

        log.info('Player successfully logged in: {}'.format(player),
                 game=self.game)
        message = self.player.to_json_str()

        return Result.OKEY, message
Пример #2
0
    def add_player(self, player: Player):
        """ Adds player to the game.
        """
        # If player is returning to the game:
        if player.idx in self.players:
            player = self.players[player.idx]
            player.in_game = True
            return player

        # Add new player to the game:
        with self._lock:

            # Check players count:
            if len(self.players) == self.num_players:
                raise errors.AccessDenied(
                    'The maximum number of players reached')
            else:
                self.players[player.idx] = player
                player.in_game = True

            # Pick first available Town on the map as player's Town:
            player_town = [t for t in self.map.towns
                           if t.player_idx is None][0]
            player_home_point = self.map.points[player_town.point_idx]
            player.set_home(player_home_point, player_town)

            # Create trains for the player:
            start_train_idx = len(self.trains) + 1
            for i in range(CONFIG.TRAINS_COUNT):
                # Create Train:
                train = Train(idx=start_train_idx + i)
                # Add Train:
                player.add_train(train)
                self.map.add_train(train)
                self.trains[train.idx] = train
                # Put the Train into Town:
                self.put_train_into_town(train, with_cooldown=False)

            # Start thread with game loop:
            if self.num_players == len(
                    self.players) and self.state == GameState.INIT:
                self.start()

        # Set player's rating:
        self.map.ratings[player.idx] = {
            'rating': player.rating,
            'name': player.name,
            'town': player_town.name,
            'idx': player.idx,
        }

        log.info(
            'New player has been connected to the game, player: {}'.format(
                player),
            game=self)

        return player
Пример #3
0
    def make_upgrade(self, player: Player, posts_idx=(), trains_idx=()):
        """ Upgrades given Posts and Trains to next level.
        """
        # Get posts from request:
        posts = []
        for post_idx in posts_idx:
            if post_idx not in self.map.posts:
                raise errors.ResourceNotFound(
                    'Post index not found, index: {}'.format(post_idx))
            post = self.map.posts[post_idx]
            if post.type != PostType.TOWN:
                raise errors.BadCommand(
                    'The post is not a Town, post: {}'.format(post))
            if post.player_idx != player.idx:
                raise errors.AccessDenied('Town\'s owner mismatch')
            posts.append(post)

        # Get trains from request:
        trains = []
        for train_idx in trains_idx:
            if train_idx not in self.trains:
                raise errors.ResourceNotFound(
                    'Train index not found, index: {}'.format(train_idx))
            train = self.trains[train_idx]
            if train.player_idx != player.idx:
                raise errors.AccessDenied('Train\'s owner mismatch')
            trains.append(train)

        # Check existence of next level for each entity:
        posts_has_next_lvl = all(
            [p.level + 1 in CONFIG.TOWN_LEVELS for p in posts])
        trains_has_next_lvl = all(
            [t.level + 1 in CONFIG.TRAIN_LEVELS for t in trains])
        if not all([posts_has_next_lvl, trains_has_next_lvl]):
            raise errors.BadCommand(
                'Not all entities requested for upgrade have next levels')

        # Check armor quantity for upgrade:
        armor_to_up_posts = sum([p.next_level_price for p in posts])
        armor_to_up_trains = sum([t.next_level_price for t in trains])
        armor_to_up = sum([armor_to_up_posts, armor_to_up_trains])
        if player.town.armor < armor_to_up:
            raise errors.BadCommand(
                'Not enough armor resource for upgrade, player\'s armor: {}, '
                'armor needed to upgrade: {}'.format(player.town.armor,
                                                     armor_to_up))

        # Check that trains are in town now:
        for train in trains:
            if not self.is_train_at_post(train, post_to_check=player.town):
                raise errors.BadCommand(
                    'The train is not in Town now, train: {}'.format(train))

        # Upgrade entities:
        for post in posts:
            player.town.armor -= post.next_level_price
            post.set_level(post.level + 1)
            log.info('Post has been upgraded, post: {}'.format(post),
                     game=self)
        for train in trains:
            player.town.armor -= train.next_level_price
            train.set_level(train.level + 1)
            log.info('Train has been upgraded, post: {}'.format(train),
                     game=self)
Пример #4
0
    def move_train(self, player, train_idx, speed, line_idx):
        """ Process action MOVE. Changes path or speed of the Train.
        """
        if train_idx not in self.trains:
            raise errors.ResourceNotFound(
                'Train index not found, index: {}'.format(train_idx))
        if line_idx not in self.map.lines:
            raise errors.ResourceNotFound(
                'Line index not found, index: {}'.format(line_idx))
        train = self.trains[train_idx]
        if train.player_idx != player.idx:
            raise errors.AccessDenied('Train\'s owner mismatch')
        if train_idx in self.next_train_moves:
            self.next_train_moves.pop(train_idx)

        # Check cooldown for the train:
        if train.cooldown > 0:
            raise errors.BadCommand(
                'The train is under cooldown, cooldown: {}'.format(
                    train.cooldown))

        # Stop the train; reverse direction on move; continue run the train:
        if speed == 0 or train.line_idx == line_idx:
            train.speed = speed

        # The train is standing:
        elif train.speed == 0:
            # The train is standing at the end of the line:
            if self.map.lines[train.line_idx].length == train.position:
                line_from = self.map.lines[train.line_idx]
                line_to = self.map.lines[line_idx]
                if line_from.points[1] in line_to.points:
                    train.line_idx = line_idx
                    train.speed = speed
                    if line_from.points[1] == line_to.points[0]:
                        train.position = 0
                    else:
                        train.position = line_to.length
                else:
                    raise errors.BadCommand(
                        'The end of the train\'s line is not connected to the next line, '
                        'train\'s line: {}, next line: {}'.format(
                            line_from, line_to))
            # The train is standing at the beginning of the line:
            elif train.position == 0:
                line_from = self.map.lines[train.line_idx]
                line_to = self.map.lines[line_idx]
                if line_from.points[0] in line_to.points:
                    train.line_idx = line_idx
                    train.speed = speed
                    if line_from.points[0] == line_to.points[0]:
                        train.position = 0
                    else:
                        train.position = line_to.length
                else:
                    raise errors.BadCommand(
                        'The beginning of the train\'s line is not connected to the next line, '
                        'train\'s line: {}, next line: {}'.format(
                            line_from, line_to))
            # The train is standing on the line (between line's points), player have to continue run the train.
            else:
                raise errors.BadCommand(
                    'The train is standing on the line (between line\'s points), '
                    'player have to continue run the train')

        # The train is moving on the line (between line's points):
        elif train.speed != 0 and train.line_idx != line_idx:
            switch_line_possible = False
            line_from = self.map.lines[train.line_idx]
            line_to = self.map.lines[line_idx]
            if train.speed > 0 and speed > 0:
                switch_line_possible = (
                    line_from.points[1] == line_to.points[0])
            elif train.speed > 0 and speed < 0:
                switch_line_possible = (
                    line_from.points[1] == line_to.points[1])
            elif train.speed < 0 and speed > 0:
                switch_line_possible = (
                    line_from.points[0] == line_to.points[0])
            elif train.speed < 0 and speed < 0:
                switch_line_possible = (
                    line_from.points[0] == line_to.points[1])

            # This train move request is valid and will be applied later:
            if switch_line_possible:
                self.next_train_moves[train_idx] = {
                    'speed': speed,
                    'line_idx': line_idx
                }
            # This train move request is invalid:
            else:
                raise errors.BadCommand(
                    'The train is not able to switch the current line to the next line, '
                    'or new speed is incorrect, train\'s line: {}, next line: {}, '
                    'train\'s speed: {}, new speed: {}'.format(
                        line_from, line_to, train.speed, speed))
Пример #5
0
 def wrapped(self, *args, **kwargs):
     if self.game is None or self.player is None:
         raise errors.AccessDenied('Login required')
     else:
         return func(self, *args, **kwargs)