def use(self, item_entity, **kwargs): results = [] item_component = item_entity.item if item_component.use_function is None: equippable_component = item_entity.equippable if equippable_component: results.append({"equip": item_entity}) else: results.append({ "message": Message(f"The {item_entity.name} cannot be used", tcod.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 item_use_result in item_use_results: if item_use_result.get("consumed"): self.remove_item(item_entity) results.extend(item_use_results) return results
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', libtcod.magenta) }) else: results.append({ 'item_added': item, 'message': Message('You pick up the {0}!'.format(item.name), libtcod.blue) }) self.items.append(item) return results
def drop_item(self, item): results = [] 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), libtcod.yellow)}) return results
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", tcod.yellow), }) else: results.append({ "item_added": item, "message": Message(f"You pick up the {item.name}", tcod.blue), }) self.items.append(item) return results
def attack(self, target): results = [] damage = self.power - target.fighter.defense if damage > 0: results.append({ 'message': Message( '{0} attacks {1} for {2} hot points.'.format( self.owner.name.capitalize(), target.name, str(damage)), libtcod.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), libtcod.white) }) return results
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(f"You dropped the {item.name}", tcod.yellow), }) return results
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(f"The {self.owner.name} is no longer confused!", tcod.red) }) return results
def use(self, item_entity, **kwargs): results = [] item_component = item_entity.item if item_component.use_function is None: results.append({'message': Message('The {0} cannot be used'.format(item_entity.name), libtcod.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 item_use_result in item_use_results: if item_use_result.get('consumed'): self.remove_item(item_entity) results.extend(item_use_results) return results
def next_floor(self, player, message_log, constants): self.dungeon_level += 1 entities = [player] self.tiles = self.initialize_tiles() self.make_map( constants["max_rooms"], constants["room_min_size"], constants["room_max_size"], constants["map_width"], constants["map_height"], player, entities, ) player.fighter.heal(player.fighter.max_hp // 2) message_log.add_message( Message( "You take a moment to rest, and recover your strength.", tcod.light_violet, )) return entities
def place_entities(self, room, entities): """ Places entities on the map :param room: The room to place the entity into :param entities: The entities to place :return: None """ max_monsters_per_room = from_dungeon_level([[2, 1], [3, 4], [5, 6]], self.dungeon_level) max_items_per_room = from_dungeon_level([[1, 1], [2, 4]], self.dungeon_level) # Get a random number of monsters number_of_monsters = randint(0, max_monsters_per_room) number_of_items = randint(0, max_items_per_room) monster_chances = { "orc": 80, "troll": from_dungeon_level([[15, 3], [30, 5], [60, 7]], self.dungeon_level), } item_chances = { "healing_potion": 35, "sword": from_dungeon_level([[5, 4]], self.dungeon_level), "shield": from_dungeon_level([[15, 8]], self.dungeon_level), "lightning_scroll": from_dungeon_level([[25, 4]], self.dungeon_level), "fireball_scroll": from_dungeon_level([[25, 6]], self.dungeon_level), "confusion_scroll": from_dungeon_level([[10, 2]], self.dungeon_level), } for i in range(number_of_monsters): # Choose a random location in the room x = randint(room.x1 + 1, room.x2 - 1) y = randint(room.y1 + 1, room.y2 - 1) if not any([ entity for entity in entities if entity.x == x and entity.y == y ]): monster_choice = random_choice_from_dict(monster_chances) if monster_choice == "orc": fighter_component = Fighter(hp=20, defense=0, power=4, xp=35) ai_component = BasicMonster() monster = Entity( x, y, "o", tcod.desaturated_green, "Orc", blocks=True, render_order=RenderOrder.ACTOR, fighter=fighter_component, ai=ai_component, ) else: fighter_component = Fighter(hp=30, defense=2, power=8, xp=100) ai_component = BasicMonster() monster = Entity( x, y, "T", tcod.darker_green, "Troll", blocks=True, render_order=RenderOrder.ACTOR, fighter=fighter_component, ai=ai_component, ) entities.append(monster) for i in range(number_of_items): x = randint(room.x1 + 1, room.x2 - 1) y = randint(room.y1 + 1, room.y2 - 1) if not any([ entity for entity in entities if entity.x == x and entity.y == y ]): item_choice = random_choice_from_dict(item_chances) if item_choice == "healing_potion": item_component = Item(use_function=heal, amount=40) item = Entity( x, y, "!", tcod.violet, "Healing Potion", render_order=RenderOrder.ITEM, item=item_component, ) elif item_choice == "sword": equippable_component = Equippable(EquipmentSlots.MAIN_HAND, power_bonus=3) item = Entity(x, y, "/", tcod.sky, "Sword", equippable=equippable_component) elif item_choice == "shield": equippable_component = Equippable(EquipmentSlots.OFF_HAND, defense_bonus=1) item = Entity( x, y, "[", tcod.darker_orange, "Shield", equippable=equippable_component, ) elif item_choice == "fireball_scroll": item_component = Item( use_function=cast_fireball, targeting=True, targeting_message=Message( "Left-click a target tile for the fireball, or right-click to cancel", tcod.light_cyan, ), damage=25, radius=3, ) item = Entity( x, y, "#", tcod.red, "Fireball scroll", render_order=RenderOrder.ITEM, item=item_component, ) elif item_choice == "confusion_scroll": item_component = Item( use_function=cast_confuse, targeting=True, targeting_message=Message( "Left-click an enemy to confuse it, or right-click to cancel.", tcod.light_cyan, ), ) item = Entity( x, y, "#", tcod.light_pink, "Confusion Scroll", render_order=RenderOrder.ITEM, item=item_component, ) else: item_component = Item(use_function=cast_lightning, damage=40, maximum_range=5) item = Entity( x, y, "#", tcod.yellow, "Lightning Scroll", render_order=RenderOrder.ITEM, item=item_component, ) entities.append(item)
def place_entities(self, room, entities, max_monsters_per_room, max_items_per_room): # Get a random number of monsters number_of_monsters = randint(0, max_monsters_per_room) number_of_items = randint(0, max_items_per_room) for i in range(number_of_monsters): # Choose a ranodom location in the room x = randint(room.x1 + 1, room.x2 - 1) y = randint(room.y1 + 1, room.y2 - 1) if not any([ entity for entity in entities if entity.x == x and entity.y == y ]): if randint(0, 100) < 80: fighter_component = Fighter(hp=10, defense=0, power=3) ai_component = BasicMonster() monster = Entity(x, y, 'o', libtcod.desaturated_green, 'Orc', blocks=True, render_order=RenderOrder.ACTOR, fighter=fighter_component, ai=ai_component) else: fighter_component = Fighter(hp=16, defense=1, power=2) ai_component = BasicMonster() monster = Entity(x, y, 'T', libtcod.darker_green, 'Troll', blocks=True, fighter=fighter_component, ai=ai_component) entities.append(monster) for i in range(number_of_items): x = randint(room.x1 + 1, room.x2 - 1) y = randint(room.y1 + 1, room.y2 - 1) if not any([ entity for entity in entities if entity.x == x and entity.y == y ]): item_chance = randint(0, 100) if item_chance < 1: item_component = Item(use_function=heal, amount=999) item = Entity(x, y, '!', libtcod.violet, 'Healing Potion', render_order=RenderOrder.ITEM, item=item_component) elif item_chance < 80: item_component = Item( use_function=cast_fireball, targeting=True, targeting_message=Message( 'Left-click a target tile for the fireball, or right-click to cancel.', libtcod.light_cyan), damage=12, radius=3) item = Entity(x, y, '#', libtcod.red, 'Fireball Scroll', render_order=RenderOrder.ITEM, item=item_component) elif item_chance < 90: item_component = Item( use_function=cast_confuse, targeting=True, targeting_message=Message( 'Left_click an enemy to confuse it, or right_click to cancel.', libtcod.light_cyan)) item = Entity(x, y, '#', libtcod.light_pink, 'Confusion Scroll', render_order=RenderOrder.ITEM, item=item_component) else: item_component = Item(use_function=cast_lightning, damage=999, maximum_range=5) item = Entity(x, y, '#', libtcod.magenta, 'Lightning Scroll', render_order=RenderOrder.ITEM, item=item_component) entities.append(item)