Exemplo n.º 1
0
    def actuate_npcs(self, level_number):
        """Actuate all NPCs on a given level

        This method actuate all NPCs on a board associated with a level. At the moment it means moving the NPCs but as the Actuators become more capable this method will evolve to allow more choice (like attack use objects, etc.)

        :param level_number: The number of the level to actuate NPCs in.
        :type int:

        Example::

            mygame.actuate_npcs(1)
        
        .. note:: This method only move NPCs when their actuator state is RUNNING. If it is PAUSED or STOPPED, theNPC is not moved.
        """
        if self.state == Constants.RUNNING:
            if type(level_number) is int:
                if level_number in self._boards.keys():
                    for npc in self._boards[level_number]['npcs']:
                        if npc.actuator.state == Constants.RUNNING:
                            self._boards[level_number]['board'].move(
                                npc, npc.actuator.next_move(), npc.step)
                else:
                    raise HacInvalidLevelException(
                        f"Impossible to actuate NPCs for this level (level number {level_number} is not associated with any board)."
                    )
            else:
                raise HacInvalidTypeException(
                    'In actuate_npcs(level_number) the level_number must be an int.'
                )
Exemplo n.º 2
0
    def animate_items(self, level_number):
        """That method goes through all the BoardItems of a given map and call
        Animation.next_frame()
        :param level_number: The number of the level to animate items in.
        :type level_number: int

        :raise: :class:`gamelib.HacExceptions.HacInvalidLevelException`
            class:`gamelib.HacExceptions.HacInvalidTypeException`

        Example::

            mygame.animate_items(1)
        """
        if self.state == Constants.RUNNING:
            if type(level_number) is int:
                if level_number in self._boards.keys():
                    for item in self._boards[level_number][
                            "board"].get_immovables():
                        if item.animation is not None:
                            item.animation.next_frame()
                    for item in self._boards[level_number][
                            "board"].get_movables():
                        if item.animation is not None:
                            item.animation.next_frame()
                else:
                    raise HacInvalidLevelException(
                        f"Impossible to animate items for this level (level number "
                        "{level_number} is not associated with any board).")
            else:
                raise HacInvalidTypeException(
                    "In animate_items(level_number) the level_number must be an int."
                )
Exemplo n.º 3
0
    def change_level(self, level_number):
        """
        Change the current level, load the board and place the player to the right place.

        Example::

            game.change_level(1)

        :param level_number: the level number to change to.
        :type level_number: int

        :raises HacInvalidTypeException: If parameter is not an int.
        """
        if type(level_number) is int:
            if self.player == None:
                raise HacException(
                    'undefined_player',
                    'Game.player is undefined. We cannot change level without a player. Please set player in your Game object: mygame.player = Player()'
                )
            if level_number in self._boards.keys():
                if self.player.pos[0] != None or self.player.pos[1] != None:
                    self._boards[self.current_level]['board'].clear_cell(
                        self.player.pos[0], self.player.pos[1])
                self.current_level = level_number
                b = self._boards[self.current_level]['board']
                b.place_item(self.player, b.player_starting_position[0],
                             b.player_starting_position[1])
            else:
                raise HacInvalidLevelException(
                    f"Impossible to change level to an unassociated level (level number {level_number} is not associated with any board).\nHave you called:\ngame.add_board({level_number},Board()) ?"
                )
        else:
            raise HacInvalidTypeException(
                'level_number needs to be an int in change_level(level_number).'
            )
Exemplo n.º 4
0
    def current_board(self):
        """
        This method return the board object corresponding to the current_level.
        
        Example::

            game.current_board().display()

        If current_level is set to a value with no corresponding board a HacException exception is raised with an invalid_level error.
        """
        if  self.current_level in self._boards.keys():
            return self._boards[self.current_level]['board']
        else:
            raise HacInvalidLevelException("The current level does not correspond to any board.")
Exemplo n.º 5
0
    def save_board(self, lvl_number, filename):
        """Save a board to a JSON file

        This method saves a Board and everything in it but the BoardItemVoid.

        Not check are done on the filename, if anything happen you get the exceptions from open().

        :param lvl_number: The level number to get the board from.
        :type lvl_number: int
        :param filename: The path to the file to save the data to.
        :type filename: str

        :raises HacInvalidTypeException: If any parameter is not of the right type
        :raises HacInvalidLevelException: If the level is not associated with a Board.
        
        Example::
        
            game.save_board( 1, 'hac-maps/level1.json')
        
        If Game.object_library is not an empty array, it will be saved also.
        """
        if type(lvl_number) is not int:
            raise HacInvalidTypeException(
                "lvl_number must be an int in Game.save_board()")
        if type(filename) is not str:
            raise HacInvalidTypeException(
                "filename must be a str in Game.save_board()")
        if lvl_number not in self._boards:
            raise HacInvalidLevelException(
                'lvl_number ' + lvl_number +
                ' does not correspond to any level associated with a board in Game.save_board()'
            )

        data = {}
        local_board = self._boards[lvl_number]['board']
        data['name'] = local_board.name
        data['player_starting_position'] = local_board.player_starting_position
        data['ui_border_left'] = local_board.ui_border_left
        data['ui_border_right'] = local_board.ui_border_right
        data['ui_border_top'] = local_board.ui_border_top
        data['ui_border_bottom'] = local_board.ui_border_bottom
        data['ui_board_void_cell'] = local_board.ui_board_void_cell
        data['size'] = local_board.size
        data['map_data'] = {}

        def _obj2ref(obj):
            ref = {
                "object": str(obj.__class__),
                "name": obj.name,
                "pos": obj.pos,
                "model": obj.model,
                "type": obj.type
            }

            if isinstance(obj, Structures.Wall):
                ref['size'] = obj.size()
            elif isinstance(obj, Structures.Treasure):
                ref['value'] = obj.value
                ref['size'] = obj.size()
            elif isinstance(
                    obj, Structures.GenericActionableStructure) or isinstance(
                        obj, Structures.GenericStructure):
                ref['value'] = obj.value
                ref['size'] = obj.size()
                ref['overlappable'] = obj.overlappable()
                ref['pickable'] = obj.pickable()
                ref['restorable'] = obj.restorable()
            elif isinstance(obj, Structures.Door):
                ref['value'] = obj.value
                ref['size'] = obj.size()
                ref['overlappable'] = obj.overlappable()
                ref['pickable'] = obj.pickable()
                ref['restorable'] = obj.restorable()
            elif isinstance(obj, NPC):
                ref['hp'] = obj.hp
                ref['max_hp'] = obj.max_hp
                ref['step'] = obj.step
                ref['remaining_lives'] = obj.remaining_lives
                ref['attack_power'] = obj.attack_power
                if obj.actuator != None:
                    if isinstance(obj.actuator, RandomActuator):
                        ref['actuator'] = {
                            'type': 'RandomActuator',
                            'moveset': obj.actuator.moveset
                        }
                    elif isinstance(obj.actuator, PathActuator):
                        ref['actuator'] = {
                            'type': 'PathActuator',
                            'path': obj.actuator.path
                        }
            return ref

        if len(self.object_library) > 0:
            data['library'] = []
            for o in self.object_library:
                data['library'].append(_obj2ref(o))

        # Now we need to run through all the cells to store anything that is not a BoardItemVoid
        for x in self.current_board()._matrix:
            for y in x:
                if not isinstance(y, BoardItemVoid) and not isinstance(
                        y, Player):
                    # print(f"Item: name={y.name} pos={y.pos} type={y.type}")
                    if str(y.pos[0]) not in data['map_data'].keys():
                        data['map_data'][str(y.pos[0])] = {}

                    data['map_data'][str(y.pos[0])][str(
                        y.pos[1])] = _obj2ref(y)
        with open(filename, 'w') as f:
            json.dump(data, f)