Beispiel #1
0
    def use(self, item_entity, **kwargs):
        results = []

        item_component = item_entity.item

        if item_component.use_function is None:
            equip_component = item_entity.equip

            if equip_component:
                results.append({'equip': item_entity})
            else:
                results.append({
                    'message':
                    Message('The {0} cannot be used!'.format(item_entity.name),
                            lc.yellow)
                })
        else:
            if item_component.targeting and not (kwargs.get('target_x')
                                                 or kwargs.get('target_y')):
                results.append({'targeting': item_entity})
            else:
                kwargs = {**item_component.function_kwargs, **kwargs}
                item_use_results = item_component.use_function(
                    self.owner, **kwargs)

                for result in item_use_results:
                    if result.get('consumed'):
                        self.remove_item(item_entity)
                results.extend(item_use_results)

        return results
Beispiel #2
0
def cast_lightning(*args, **kwargs):
    caster = args[0]
    entities = kwargs.get('entities')
    fov_map = kwargs.get('fov_map')
    damage = kwargs.get('damage')
    maximum_range = kwargs.get('maximum_range')

    results = []

    target = None
    closest_distance = maximum_range + 1

    for entity in entities:
        if entity.fighter and entity != caster and lc.map_is_in_fov(
                fov_map, entity.x, entity.y):
            distance = caster.distance_to(entity)

            if distance < closest_distance:
                target = entity
                closest_distance = distance

    if target:
        results.append({
            'consumed':
            True,
            'target':
            target,
            'message':
            Message('A lightning bolt strikes {0} for {1} damage.'.format(
                target.name, damage))
        })
        results.extend(target.fighter.take_damage(damage))
    else:
        results.append({
            'consumed':
            False,
            'target':
            None,
            'message':
            Message('No enemy is close enough to strike.', lc.red)
        })

    return results
Beispiel #3
0
def cast_confuse(*args, **kwargs):
    entities = kwargs.get('entities')
    fov_map = kwargs.get('fov_map')
    target_x = kwargs.get('target_x')
    target_y = kwargs.get('target_y')

    results = []

    if not lc.map_is_in_fov(fov_map, target_x, target_y):
        results.append({
            'consumed':
            False,
            'message':
            Message('You cannot target you cannot see.', lc.yellow)
        })
        return results

    for entity in entities:
        if entity.x == target_x and entity.y == target_y and entity.ai:
            confused_ai = ConfusedMonster(entity.ai, 10)
            confused_ai.owner = entity
            entity.ai = confused_ai

            results.append({
                'consumed':
                True,
                'message':
                Message(
                    'The eyes of the {0} look vacant as he begins to stumble around.'
                    .format(entity.name), lc.green)
            })

            break
    else:
        results.append({
            'consumed':
            False,
            'message':
            Message('There is no targetable enemy at the location.', lc.yellow)
        })

    return results
Beispiel #4
0
    def add_item(self, item):
        results = []

        if len(self.items) >= self.capacity:
            results.append({
                'item_added':
                None,
                'message':
                Message('You cannot carry any more, your inventory is full.',
                        lc.yellow)
            })
        else:
            results.append({
                'item_added':
                item,
                'message':
                Message('You pick up the {0}!'.format(item.name), lc.blue)
            })
            self.items.append(item)

        return results
Beispiel #5
0
def kill_enemy(enemy):
    death_message = Message('{0} dies!'.format(enemy.name.capitalize()),
                            lc.orange)

    enemy.char = '%'
    enemy.colour = lc.dark_red
    enemy.blocks = False
    enemy.fighter = None
    enemy.ai = None
    enemy.name = 'remains of ' + enemy.name
    enemy.render_order = RenderOrder.CORPSE

    return death_message
Beispiel #6
0
def cast_fireball(*args, **kwargs):
    entities = kwargs.get('entities')
    fov_map = kwargs.get('fov_map')
    damage = kwargs.get('damage')
    radius = kwargs.get('radius')
    target_x = kwargs.get('target_x')
    target_y = kwargs.get('target_y')

    results = []

    if not lc.map_is_in_fov(fov_map, target_x, target_y):
        results.append({
            'consumed':
            False,
            'message':
            Message('You cannot target a tile you can\'t see.', lc.yellow)
        })
        return results
    results.append({
        'consumed':
        True,
        'message':
        Message(
            'The fireball explodes, burning everything within {0} tiles!'.
            format(radius), lc.orange)
    })

    for entity in entities:
        if entity.distance(target_x, target_y) <= radius and entity.fighter:
            results.append({
                'message':
                Message(
                    '{0} is burned for {1} damage.'.format(
                        entity.name, damage), lc.orange)
            })
            results.extend(entity.fighter.take_damage(damage))

    return results
Beispiel #7
0
def heal(*args, **kwargs):
    entity = args[0]
    amount = kwargs.get('amount')

    results = []

    if entity.fighter.health == entity.fighter.max_health:
        results.append({
            'consumed':
            False,
            'message':
            Message('You are already at full health.', lc.yellow)
        })
    else:
        entity.fighter.heal(amount)
        results.append({
            'consumed':
            True,
            'message':
            Message('Your wounds start to feel better!', lc.green)
        })

    return results
Beispiel #8
0
    def attack(self, target):
        results = []

        damage = self.power - target.fighter.defense

        if damage > 0:
            results.append({
                'message':
                Message(
                    "{0} attacks {1} for {2} points of damage.".format(
                        self.owner.name.capitalize(), target.name,
                        str(damage)), lc.white)
            })
            results.extend(target.fighter.take_damage(damage))
        else:
            results.append({
                'message':
                Message(
                    "{0} attacks {1} but does no damage.".format(
                        self.owner.name.capitalize(), target.name), lc.white)
            })

        return results
Beispiel #9
0
    def take_turn(self,target,fov_map,game_map,entities):
        results=[]

        if self.number_of_turns>0:
            random_x=self.owner.x+randint(0,2)-1
            random_y=self.owner.y+randint(0,2)-1

            if random_x != self.owner.x and random_y != self.owner.y:
                self.owner.move_towards(random_x,random_y,game_map,entities)
            
            self.number_of_turns-=1
        else:
            self.owner.ai=self.previous_ai
            results.append({'message':Message('The {0} is no longer confused!'.format(self.owner.name),lc.red)})

        return results
Beispiel #10
0
    def from_json(json_data):
        if json_data.get('use_function'):
            use_function = getattr(itemfunctions,
                                   json_data.get('use_function'))
        else:
            use_function = None
        targeting = json_data.get('targeting')
        if json_data.get('targeting_message'):
            targeting_message = Message.from_json(
                json_data.get('targeting_message'))
        else:
            targeting_message = None
        function_kwargs = json_data.get('function_kwargs')

        return Item(use_function, targeting, targeting_message,
                    **function_kwargs)
Beispiel #11
0
    def next_floor(self, player, message_log, constants):
        self.floor += 1
        entities = [player]

        self.tiles = self.initialise_tiles()
        self.make_map(constants['max_rooms'], constants['room_min_size'],
                      constants['room_max_size'], constants['map_width'],
                      constants['map_height'], player, entities,
                      constants['tile_data'])

        player.fighter.heal(player.fighter.max_health // 2)

        message_log.add_message(
            Message('You take a moment to rest and recover your strength.',
                    lc.light_violet))

        return entities
Beispiel #12
0
    def drop_item(self, item):
        results = []

        if self.owner.equipment.main_hand == item or self.owner.equipment.off_hand == item:
            self.owner.equipment.toggle_equip(item)

        item.x = self.owner.x
        item.y = self.owner.y

        self.remove_item(item)
        results.append({
            'item_dropped':
            item,
            'message':
            Message('You dropped the {0}'.format(item.name), lc.yellow)
        })

        return results
Beispiel #13
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    fov_map = initialise_fov(game_map)

    key = lc.Key()
    mouse = lc.Mouse()

    game_state = GameStates.PLAYER_TURN
    previous_game_state = game_state

    targeting_item = None

    while not lc.console_is_window_closed():
        lc.sys_check_for_event(lc.EVENT_KEY_PRESS | lc.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants['fov_radius'],
                          constants['fov_light_walls'],
                          constants['fov_algorithm'])

        render_all(con, panel, game_map, entities, player, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'], mouse,
                   constants['tile_data'], game_state)

        fov_recompute = False

        lc.console_flush()

        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        move = action.get('move')
        pickup = action.get('pickup')
        wait = action.get('wait')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        inventory_index = action.get('inventory_index')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_char_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        player_turn_results = []

        if move and game_state == GameStates.PLAYER_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    fov_recompute = True
                game_state = GameStates.ENEMY_TURN

        elif wait:
            game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYER_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(
                    Message('There is nothing here to pick up.', lc.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]

            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if take_stairs and game_state == GameStates.PLAYER_TURN:
            for entity in entities:
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    entities = game_map.next_floor(player, message_log,
                                                   constants)
                    fov_map = initialise_fov(game_map)
                    fov_recompute = True
                    lc.console_clear(con)

                    break
            else:
                message_log.add_message(
                    Message('There are no stairs here.', lc.yellow))

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_health += 20
                player.fighter.health += 20
            elif level_up == 'pow':
                player.fighter.base_power += 1
            elif level_up == 'def':
                player.fighter.base_defense += 1
            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click

                item_use_results = player.inventory.use(targeting_item,
                                                        entities=entities,
                                                        fov_map=fov_map,
                                                        target_x=target_x,
                                                        target_y=target_y)

                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY,
                              GameStates.CHARACTER_SCREEN):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                if not game_state == GameStates.PLAYER_DEAD:
                    # save_game(player,entities,game_map,message_log,game_state)
                    json_save_game(player, entities, game_map, message_log,
                                   game_state, con, constants['screen_width'],
                                   constants['screen_height']
                                   )  #Takes about 15 times longer
                return True

        if fullscreen:
            lc.console_set_fullscreen(not lc.console_is_fullscreen())

        for result in player_turn_results:
            message = result.get('message')
            dead_entity = result.get('dead')
            item_added = result.get('item_added')
            item_consumed = result.get('consumed')
            item_dropped = result.get('item_dropped')
            equip = result.get('equip')
            targeting = result.get('targeting')
            targeting_cancelled = result.get('targeting_cancelled')
            xp = result.get('xp')

            if message:
                message_log.add_message(message)

            if targeting_cancelled:
                game_state = previous_game_state
                message_log.add_message(Message('Targeting cancelled.'))

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_enemy(dead_entity)
                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)
                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.append(item_dropped)
                game_state = GameStates.ENEMY_TURN

            if equip:
                equip_results = player.equipment.toggle_equip(equip)

                for result in equip_results:
                    equipped = result.get('equipped')
                    dequipped = result.get('dequipped')

                    if equipped:
                        message_log.add_message(
                            Message('You equipped the {0}'.format(
                                equipped.name)))
                    if dequipped:
                        message_log.add_message(
                            Message('You unequipped the {0}'.format(
                                dequipped.name)))

                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYER_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(
                    Message('You gain {0} experience points.'.format(xp)))

                if leveled_up:
                    message_log.add_message(
                        Message(
                            'Your battle skills grow stronger! You reached level {0}'
                            .format(player.level.current_level) + '!',
                            lc.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for result in enemy_turn_results:
                        message = result.get('message')
                        dead_entity = result.get('dead')

                        if message:
                            message_log.add_message(message)
                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_enemy(dead_entity)
                            message_log.add_message(message)
                            if game_state == GameStates.PLAYER_DEAD:
                                break
                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYER_TURN
Beispiel #14
0
def kill_player(player):
    player.char = '%'
    player.colour = lc.dark_red
    player.name = 'player\'s corpse'

    return Message('You died!', lc.red), GameStates.PLAYER_DEAD