コード例 #1
0
ファイル: AI.py プロジェクト: Sunnigen/Impact-Warrior
    def take_turn(self, fov_map, game_map, entities):
        results = []
        mob = self.owner
        mob.fighter.fov_range = 1

        # Blind Mob AI
        if self.duration > 0:
            self.duration -= 1
        else:
            # Blind Wore Off Restore Default
            mob.ai = self.previous_ai
            mob.fighter.fov_range = MOBS.get(mob.json_index).get('fov_range')
            results.append({
                'message':
                Message('The %s can see clearly now!' % mob.name, libtcod.red)
            })
        return results
コード例 #2
0
    def use(self, item_entity, **kwargs):
        results = []
        item_component = item_entity.item
        # Check if Item Has a "Use" or "Equip" Function
        if not item_component.use_function:
            equippable_component = item_entity.equippable
            if equippable_component:
                results.append({'equip': item_entity})
            else:
                results.append({
                    'message':
                    Message('The %s cannot be used.' % item_entity.name,
                            libtcod.yellow)
                })
        else:
            # Check Item Type if Targeting Component is Required
            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}

                # Most Important Connecting Function
                # Note: Pass the user and various catch-all-keyword-args
                item_use_results = item_component.use_function(
                    self.owner, **kwargs)

                # Check if Item is Altered after Usage
                for item_use_result in item_use_results:
                    # Remove Item from Inventory
                    if item_use_result.get('consumed'):
                        self.remove_item(item_entity)
                        break

                    # Keep Item in Inventory
                    if item_use_result.get('reuseable'):
                        # results.append({'message': Message("")})
                        break

                results.extend(item_use_results)

        return results
コード例 #3
0
def break_container(*args, **kwargs):
    # print('break_container')
    attacker_entity = args[0]
    container_entity = args[1]
    entities = kwargs.get('entities')


    # print('container_entity:', container_entity.name)
    # print('attacker_entity:', attacker_entity.name)
    # print('container inventory:', container_entity.inventory.items)

    results = [{"change_map_object": [container_entity, 2],
                "spawn_particle": ["hit", container_entity.position.x, container_entity.position.y, None],
                'message': Message('You break open the {}...'.format(container_entity.name.lower()), tcod.yellow)}]

    for item in container_entity.inventory.items:
        entities.append(item)

    container_entity.inventory.drop_all_items()
    return results
コード例 #4
0
def kill_player(player):
    player.char = "%"  # 37
    player.color = libtcod.dark_red

    # return 'You died!', GameStates.PLAYER_DEAD
    return Message('You died!', libtcod.red), GameStates.PLAYER_DEAD
コード例 #5
0
ファイル: AI.py プロジェクト: Sunnigen/Impact-Warrior
    def advance_on_current_target(self, entities, game_map, fov_map, dist,
                                  radius, results, target_x, target_y):
        mob = self.owner

        # Check to Cast Spell or Perform Skill
        can_cast_spells = getattr(self.owner.spellcaster, 'has_spells', None)
        if self.current_target and can_cast_spells:
            if self.owner.spellcaster.has_spells:

                # Select Spell
                # Check Self HP to Heal
                if self.owner.fighter.hp <= self.owner.fighter.max_hp // 2 and self.owner.spellcaster.has_spell_type(
                        "restorative"):
                    try:
                        spell_to_cast = choice([
                            spell for spell in self.owner.spellcaster.spells
                            if spell.type & {"restorative"} and spell.is_ready
                        ])
                        target = self.owner
                    except IndexError:
                        # Empty sequence/no spells
                        spell_to_cast = None
                        target = None

                elif self.owner.faction.check_enemy(
                        self.current_target.faction.faction_name):
                    try:
                        spell_to_cast = choice([
                            spell for spell in self.owner.spellcaster.spells
                            if spell.type
                            & {"offensive", "buff", "environment"}
                            and spell.is_ready
                        ])
                        target = self.current_target
                    except IndexError:
                        # Empty sequence/no spells
                        spell_to_cast = None
                        target = None

                else:
                    spell_to_cast = None
                    target = None

                if spell_to_cast:
                    results.extend(
                        self.owner.spellcaster.cast(spell_to_cast,
                                                    caster=self.owner,
                                                    target=target))
                    return results

                # Check Enemy to cast Spell
                # if self.owner.faction.check_enemy(self.current_target.faction.faction_name) and \
                #     mob.position.distance_to(self.current_target.position.x, self.current_target.position.y) < 5:
                #     # Select Self Buff or Offensive Spell
                #     results.extend(self.owner.spellcaster.cast(cast_thorn_spike, spell, target=self.current_target))
                #     return results

        # Check if Stuck to Reset Path
        if self.stuck_time > self.stuck_time_max:
            self.path = []
            self.stuck_time = 0

        # Target is Within Range, Attack
        if self.current_target:
            if self.current_target.fighter.hp > 0 and \
                    mob.position.distance_to(self.current_target.position.x, self.current_target.position.y) <= self.owner.fighter.attack_range:
                # print('# Target is Within Range, Attack')

                attack_results = mob.fighter.attack(self.current_target)
                results.extend(attack_results)
                return results

        # Close distance to Target or Evade
        if (self.current_target and not self.path) or \
                (self.last_target_position and not self.path) or \
                (self.current_target and not (target_y, target_x) in self.path):

            self.path = mob.position.movement_function(
                target_x,
                target_y,
                game_map,
            )
            # self.path = mob.position.move_astar(target_x, target_y, game_map)

        # Move Entity to Next Floor if Seeking
        if self.encounter.main_target == game_map.stairs and \
                self.owner.position.x == game_map.stairs.position.x and \
                self.owner.position.y == game_map.stairs.position.y:
            entities.remove(self.owner)
            self.encounter.mob_list.remove(self.owner)
            game_map.next_floor_entities.append(self.owner)

            tile_index = game_map.tileset_tiles[self.owner.position.y][
                self.owner.position.x]
            game_map.tile_cost[self.owner.position.y][
                self.owner.position.x] = game_map.tile_set.get(
                    '%s' % tile_index).get('tile_cost')
            results.append({
                'message':
                Message('{} ascended to the next level!'.format(
                    self.owner.name))
            })

        # Finally Move
        if len(self.path) > 0:
            results.extend(self.move_on_path(game_map, entities, results))
            self.direction_vector = get_direction(self.owner.position.x,
                                                  self.owner.position.y,
                                                  target_x, target_y)

        return results
コード例 #6
0
    def activate_event(self, entities, particles):
        results = []
        if self.event_type == 'spawn_mob':
            mob_indexes = self.function_kwargs.get('mobs')
            faction = self.function_kwargs.get('faction')
            ai_type = self.function_kwargs.get('ai_type')
            area = self.function_kwargs.get('area_of_interest')
            spawn_x, spawn_y = self.function_kwargs.get('position')
            target_entity = self.function_kwargs.get('target_entity')
            follow_entity = self.function_kwargs.get('follow_entity')
            origin_x = self.function_kwargs.get('origin_x')
            origin_y = self.function_kwargs.get('origin_y')
            e = Encounter(self.game_map,
                          area,
                          len(self.game_map.encounters) + 1,
                          ai_type=ai_type)

            if self.game_map.player.position.distance_to(spawn_x, spawn_y) < 5:
                results.append({
                    'message':
                    Message(
                        "You spot reinforcements coming from the above floor!",
                        tcod.dark_yellow)
                })
            else:
                results.append({
                    'Message':
                    Message("You hear barking and yelling in the distance...",
                            tcod.dark_yellow)
                })
            for mob_index in mob_indexes:
                x, y = self.game_map.obtain_closest_spawn_point(
                    spawn_x, spawn_y)
                mob_stats = MOBS.get(mob_index)
                if x and y:
                    self.game_map.tile_cost[y][x] = 99
                    entities.append(
                        generate_mob(x,
                                     y,
                                     mob_stats,
                                     mob_index,
                                     e,
                                     faction,
                                     ai_type,
                                     entities,
                                     follow_entity=follow_entity,
                                     target_entity=target_entity,
                                     origin_x=origin_x,
                                     origin_y=origin_y))
                else:
                    print(
                        'Error! Coudn\'t find open spawn point for {} at ({}, {})'
                        .format(mob_stats.get('name'), spawn_x, spawn_y))
                # (x, y, mob_stats, mob_index, encounter_group, faction, ai, entities, dialogue_component=None):
        elif self.event_type == 'open_gate':
            # print('event_type:', self.event_type)
            map_objects = self.function_kwargs.get('map_objects')
            default_floor_tile = self.function_kwargs.get(
                'default_floor_tile', "2")

            for map_object in map_objects:
                # print('removing : ', map_object)
                self.game_map.map_objects.remove(map_object)
                place_tile(self.game_map, map_object.position.x,
                           map_object.position.y, default_floor_tile)
                # results.append({"change_map_object": [map_object, 2], "message": Message("The {} has opened!".format(map_object.name))})
            results.append({
                "message":
                Message("The {} has opened!".format(map_object.name))
            })

        return results
コード例 #7
0
def create_item_entity(item_index, x=None, y=None):
    item_stats = ITEMS.get(item_index)
    if x and y:
        position_component = Position(x, y)
    else:
        position_component = None

    # Assemble an Item Entity with it's Required Components
    if item_stats.get('type') == 'consumable':
        item_component = Item(
            use_function=eval(item_stats.get('use_function', "nothing")),
            amount=item_stats.get('amount'),
            radius=item_stats.get('radius'),
            damage=item_stats.get('damage'),
            targeting_message=Message(item_stats.get('targeting_message')),
            targeting=item_stats.get('targeting'),
            maximum_range=item_stats.get('range'),
            targeting_type=item_stats.get('targeting_type'),
            description=item_stats.get('description'))

        item_entity = Entity(item_stats.get('glyph'),
                             item_stats.get('color'),
                             item_stats.get('name'),
                             json_index=item_index,
                             position=position_component,
                             render_order=RenderOrder.ITEM,
                             item=item_component)

    elif item_stats.get('type') == 'reuseable':
        item_component = Item(use_function=eval(
            item_stats.get('use_function', "nothing")),
                              name=item_stats.get('name'),
                              text=item_stats.get('text'),
                              description=item_stats.get('description'))

        item_entity = Entity(
            item_stats.get('glyph'),
            item_stats.get('color'),
            item_stats.get('name'),
            position=position_component,
            json_index=item_index,
            render_order=RenderOrder.ITEM,
            item=item_component,
        )

    elif item_stats.get('type') == 'equip':
        equippable_component = Equippable(
            item_stats.get('slot'),
            power_bonus=item_stats.get('attack', 0),
            defense_bonus=item_stats.get('defense', 0),
            max_hp_bonus=item_stats.get('hp', 0),
            description=item_stats.get('description'))

        item_entity = Entity(item_stats.get('glyph'),
                             item_stats.get('color'),
                             item_stats.get('name'),
                             position=position_component,
                             render_order=RenderOrder.ITEM,
                             json_index=item_index,
                             equippable=equippable_component)
    else:
        print(
            'Item Name: %s, Item type: %s isn\'t a suitable item type! Double check ./assets/item.json'
            % (item_stats.get('name'), item_stats.get('type')))
        raise ValueError

    return item_entity
コード例 #8
0
def _generate_random_items(number_of_items, dungeon_level):
    # Create Item Entities
    item_entities = []
    item_chances = {
        item: spawn_chance(
            [[item_stats.get('spawn_chance'),
              item_stats.get('item_level')]], dungeon_level)
        for item, item_stats in ITEMS.items()
        if not item_stats.get('unique', False)
    }

    # Generate Random Number of Items
    for i in range(number_of_items):
        # Randomly Select an Item to Spawn
        item_index = random_choice_from_dict(item_chances)
        item_stats = ITEMS[item_index]

        if item_stats.get('type') == 'consumable':
            item_component = Item(
                use_function=eval(item_stats.get('use_function', "nothing")),
                amount=item_stats.get('amount'),
                radius=item_stats.get('radius'),
                damage=item_stats.get('damage'),
                targeting_message=Message(item_stats.get('targeting_message')),
                targeting=item_stats.get('targeting'),
                maximum_range=item_stats.get('range'),
                targeting_type=item_stats.get('targeting_type'),
                description=item_stats.get('description'))

            item_entity = Entity(item_stats.get('glyph'),
                                 item_stats.get('color'),
                                 item_stats.get('name'),
                                 item_index,
                                 render_order=RenderOrder.ITEM,
                                 item=item_component)

        elif item_stats.get('type') == 'reuseable':
            item_component = Item(use_function=eval(
                item_stats.get('use_function', "nothing")),
                                  name=item_stats.get('name'),
                                  text=item_stats.get('text'),
                                  description=item_stats.get('description'))

            item_entity = Entity(
                item_stats.get('glyph'),
                item_stats.get('color'),
                item_stats.get('name'),
                item_index,
                render_order=RenderOrder.ITEM,
                item=item_component,
            )

        elif item_stats.get('type') == 'equip':
            equippable_component = Equippable(
                item_stats.get('slot'),
                power_bonus=item_stats.get('attack', 0),
                defense_bonus=item_stats.get('defense', 0),
                max_hp_bonus=item_stats.get('hp', 0),
                description=item_stats.get('description'))

            item_entity = Entity(item_stats.get('glyph'),
                                 item_stats.get('color'),
                                 item_stats.get('name'),
                                 item_index,
                                 equippable=equippable_component)
        item_entities.append(item_entity)

    return item_entities
コード例 #9
0
def cast_teleport(*args, **kwargs):
    caster = args[0]
    game_map = kwargs.get("game_map")
    target_x = kwargs.get("target_x")
    target_y = kwargs.get("target_y")
    reveal_all = kwargs.get("reveal_all")

    results = [{
        'message':
        Message('You focus on the crystal\'s reflection...', tcod.light_green)
    }]

    if (game_map.walkable[target_y][target_x]
            and game_map.tile_cost[target_y][target_x] == 1
            and game_map.explored[target_y][target_x]) or reveal_all:
        results.append({
            'consumed':
            True,
            'message':
            Message('A bright light engulfs you for a moment.',
                    tcod.light_green)
        })

        # 10% Chance of Teleporting to to a Random Location!
        teleport_roll = randint(1, 10)
        if teleport_roll == 1:

            # Attempt to Find a Random Location
            max_tries = 30
            tries = 0
            random_x, random_y = None, None
            while tries < max_tries:
                random_x = randint(1, game_map.width - 1)
                random_y = randint(1, game_map.height - 1)

                # print('\n', random_x, random_y)
                # print(game_map.walkable[random_y][random_x], game_map.tile_cost[random_y][random_x], game_map.tileset_tiles[random_y][random_x])
                if game_map.walkable[random_y][random_x] and game_map.tile_cost[
                        random_y][random_x] == 1:
                    break
                random_x, random_y = None, None
                tries += 1

            # Fail safe if no proper location is found
            if not random_x or not random_y:
                results.append({
                    'message':
                    Message(
                        'Nothing seems to have happened? You no longer have a crystal in your hands.',
                        tcod.light_yellow)
                })
            else:
                results.append({
                    'message':
                    Message(
                        'You have teleported somewhere else entirely? You look around warily.',
                        tcod.light_red)
                })
                game_map.walkable[random_y][random_x] = True
                game_map.transparent[random_y][random_x] = True
                caster.position.x, caster.position.y = random_x, random_y

        else:
            results.append({
                'message':
                Message('You have teleported successfully!', tcod.light_green)
            })
            game_map.walkable[caster.position.y][caster.position.x] = True
            game_map.transparent[caster.position.y][caster.position.x] = True
            caster.position.x, caster.position.y = target_x, target_y
    else:
        results.extend([{
            'consumed':
            False,
            'message':
            Message(
                'But you can\'t focus on the location. Nothing appears to have happened.',
                tcod.yellow)
        }])
    return results
コード例 #10
0
def cast_fireball(*args, **kwargs):
    caster = args[0]
    entities = kwargs.get('entities')
    fov_map = kwargs.get('fov_map')
    damage = kwargs.get('damage')
    radius = kwargs.get('radius')
    game_map = kwargs.get('game_map')
    target_x = kwargs.get('target_x')
    target_y = kwargs.get('target_y')

    results = []

    # Tile not within range
    if not fov_map.fov[target_x][target_y]:
        results.append({
            'consumed':
            False,
            'message':
            Message('You cannot target this area!', tcod.yellow)
        })
        return results

    results.append({
        'consumed':
        True,
        'message':
        Message(
            'The fireball explodes, burning everything within %s tiles!' %
            radius, tcod.orange)
    })

    # Damage Entities in Radius
    # _entities = [entity for entity in entities if entity.position]
    for entity in entities:
        if entity.position.distance(target_x,
                                    target_y) <= radius and entity.fighter:
            results.append({
                'message':
                Message(
                    'The %s gets burned for %s hit points.' %
                    (entity.name, damage), tcod.orange)
            })
            results.extend(entity.fighter.take_damage(damage, caster))

    # "Destroy" Map Object
    print(game_map.map_objects)
    for entity in game_map.map_objects:
        if entity.position.distance(
                target_x, target_y
        ) <= radius and entity.map_object.breakable and "flammable" in entity.map_object.properties:
            # map_object_component = entity.map_object

            if entity.inventory:

                for item in entity.inventory.items:
                    entities.append(item)

                entity.inventory.drop_all_items()

            results.append({"change_map_object": [entity, 2]})

    # Apply Fire Particle to Each Affected Tile
    # lower_bound = radius // 2
    # upper_bound = ceil(radius / 2)
    fire_particle_system = ParticleSystem()
    for x in range(target_x - radius, target_x + radius + 1):
        for y in range(target_y - radius, target_y + radius + 1):

            dx = target_x - x
            dy = target_y - y

            distance_squared = dx * dx + dy * dy

            # Check if Obstacle or Flammable Tile
            if game_map.tile_cost[y][
                    x] != 0 and distance_squared <= radius * radius:
                results.append(
                    {"spawn_particle": ["fire", x, y, fire_particle_system]})

    return results
コード例 #11
0
def cast_lightning(*args, **kwargs):
    caster = args[0]
    entities = kwargs.get('entities')
    # fov_map = kwargs.get('fov_map')
    damage = kwargs.get('damage')
    game_map = kwargs.get("game_map")
    maximum_range = kwargs.get('maximum_range')

    results = []

    target = None
    closest_distance = maximum_range + 1

    # Search Closest Entity
    for entity in entities:
        if entity.fighter and entity != caster and (
                entity.position.x,
                entity.position.y) in caster.fighter.curr_fov_map:
            distance = caster.position.distance_to(entity.position.x,
                                                   entity.position.y)

            if distance < closest_distance and caster.faction.check_enemy(
                    entity.faction.faction_name):
                target = entity
                closest_distance = distance

    if target:
        lightning_astar_path = caster.position.move_astar(target.position.x,
                                                          target.position.y,
                                                          game_map,
                                                          diagonal_cost=1.00)
        results.append({
            'consumed':
            True,
            'target':
            target,
            'message':
            Message(
                'A lightning bolt strikes %s with a loud thunder! %s sustains %s damage.'
                % (target.name, target.name, damage))
        })
        results.extend(target.fighter.take_damage(damage, caster))

        # Create Lightning Particles Along Path to Target Entity
        # TODO: Check if surrounding tiles conduct electricity
        lightning_particle_system = ParticleSystem()
        for path_x, path_y in lightning_astar_path:
            results.append({
                'spawn_particle':
                ["lightning", path_y, path_x, lightning_particle_system]
            })

    else:
        results.append({
            'consumed':
            False,
            'target':
            None,
            'message':
            Message('No enemy is close enough to strike.', tcod.red)
        })

    return results
コード例 #12
0
def see_through_key_hole(*args, **kwargs):
    door_entity = args[1]
    results = [{'see_through_key_hole': door_entity, 'message': Message('You look through the key hole into the next room.', tcod.yellow)}]
    return results
コード例 #13
0
def event_gate(*args, **kwargs):
    return [{'message': Message("You can't spot a keyhole. There has to be another way to open the gate?", tcod.dark_yellow)}]
コード例 #14
0
def already_toggle_switch(*args, **kwargs):
    return [{'message': Message("The lever has already been pulled.", tcod.dark_yellow)}]
コード例 #15
0
def burn(*args, **kwargs):
    results = []
    caster = args[0]
    stove_entity = args[1]
    burn_damage = 10
    player = kwargs.get('player')

    if caster == player:
        identifier = "You burn yourself for {} damage.".format(burn_damage)
        tcod_color = tcod.flame
    else:
        identifier = "The {} burns itself for {} damage.".format(caster.name, burn_damage)
        tcod_color = tcod.dark_yellow
    fire_particle_system = ParticleSystem()
    results.append({"spawn_particle": ["fire", caster.position.x, caster.position.y, fire_particle_system], 'message': Message('{}'.format(identifier), tcod_color)})
    results.extend(caster.fighter.take_damage(burn_damage))
    return results
コード例 #16
0
def empty_chest(*args, **kwargs):
    # print('empty_chest')
    results = []
    results.append({'chest': False, 'message': Message('The chest is already been opened.', tcod.yellow)})
    return results