示例#1
0
def kill_player(player, colors):
    player.char = '%'
    player.color = colors.get('dark_red')

    return Message('You died!', colors.get('red')), GameStates.PLAYER_DEAD
示例#2
0
    def place_entities(self, room, entities, max_monters_per_room,
                       max_items_per_room):
        # Get a random number of monsters
        number_of_monsters = randint(0, max_monters_per_room)
        number_of_items = randint(0, max_items_per_room)

        monster_chances = {'orc': 80, 'troll': 20}
        item_chances = {
            'healing_potion': 70,
            'lightning_scroll': 10,
            'fireball_scroll': 10,
            'confusion_scroll': 10
        }

        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':
                    treasure_drop = randint(1, 20)
                    fighter_component = Fighter(hp=10,
                                                defense=0,
                                                power=1,
                                                xp=35,
                                                coins=treasure_drop)
                    ai_component = BasicMonster()
                    monster = Entity(x,
                                     y,
                                     'o',
                                     libt.desaturated_green,
                                     'Orc',
                                     blocks=True,
                                     render_order=RenderOrder.ACTOR,
                                     fighter=fighter_component,
                                     ai=ai_component)
                else:
                    treasure_drop = randint(1, 50)
                    fighter_component = Fighter(hp=16,
                                                defense=1,
                                                power=1,
                                                xp=100,
                                                coins=treasure_drop)
                    ai_component = BasicMonster()
                    monster = Entity(x,
                                     y,
                                     'T',
                                     libt.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):
            # 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
            ]):
                item_choice = random_choice_from_dict(item_chances)

                if item_choice == 'healing_potion':
                    item_component = Item(use_function=heal, amount=4)
                    item = Entity(x,
                                  y,
                                  '!',
                                  libt.violet,
                                  'Healing Potion',
                                  render_order=RenderOrder.ITEM,
                                  item=item_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.',
                            libt.light_cyan),
                        damage=12,
                        radius=3)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libt.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.',
                            libt.light_cyan))
                    item = Entity(x,
                                  y,
                                  '#',
                                  libt.light_pink,
                                  'Confusion Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                else:
                    item_component = Item(use_function=cast_lightning,
                                          damage=20,
                                          maximum_range=5)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libt.yellow,
                                  'Lightning Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)

                entities.append(item)
def kill_monster(monster):
    death_message = Message('{0} is dead!'.format(monster.name.capitalize()), libtcod.orange)
    monster.set_corpse()
    return death_message
def get_scroll_choice(item_choice, x, y):
    if 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.', libtcod.light_cyan),
                              damage=25, radius=3)
        item = Entity(x, y, '#', libtcod.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.', libtcod.light_cyan))
        item = Entity(x, y, '#', libtcod.light_pink, 'Confusion Scroll', render_order=RenderOrder.ITEM,
                      item=item_component)
    elif item_choice == 'lightning_scroll':
        item_component = Item(use_function=cast_lightning, damage=40, maximum_range=5)
        item = Entity(x, y, '#', libtcod.yellow, 'Lightning Scroll', render_order=RenderOrder.ITEM,
                      item=item_component)
    else:
        item_component = Item(use_function=None, damage=0, maximum_range=0)
        item = Entity(x, y, '?', libtcod.yellow, 'ERROR SCROLL', render_order=RenderOrder.ITEM,
                      item=item_component)

    return item
示例#5
0
def kill_player(player):
    player.char = '%'
    player.color = 'dark red'

    return Message('You were destroyed!', 'red'), GameStates.PLAYER_DEAD
示例#6
0
    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 random location in the room
            x = randint(room.x1 + 1, room.x2 - 1)
            y = randint(room.y1 + 1, room.y2 - 1)

            # Check if an entity is already in that location
            if not any([
                    entity
                    for entity in entities if entity.x == x and entity.y == y
            ]):
                if randint(0, 100) < 70:
                    fighter_component = Fighter(hp=6, defense=0, power=4)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     'i',
                                     libtcod.light_lime,
                                     'Possessed Serf',
                                     blocks=True,
                                     render_order=RenderOrder.ACTOR,
                                     fighter=fighter_component,
                                     ai=ai_component)
                elif randint(0, 100) < 60:
                    fighter_component = Fighter(hp=10, defense=0, power=5)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     'd',
                                     libtcod.light_crimson,
                                     'Lesser Demon',
                                     blocks=True,
                                     fighter=fighter_component,
                                     render_order=RenderOrder.ACTOR,
                                     ai=ai_component)
                else:
                    fighter_component = Fighter(hp=15, defense=1, power=6)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     'D',
                                     libtcod.crimson,
                                     'Demon Knight',
                                     blocks=True,
                                     fighter=fighter_component,
                                     render_order=RenderOrder.ACTOR,
                                     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 < 70:
                    item_component = Item(use_function=heal, amount=4)
                    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 tile to cast fireball, or esc to cancel',
                            libtcod.light_cyan),
                        damage=12,
                        radius=3)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.red,
                                  'Hellfire Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_chance < 85:
                    item_component = Item(
                        use_function=cast_confuse,
                        targeting=True,
                        targeting_message=Message(
                            'Left click an enent to confuse it, or esc to cancel.',
                            libtcod.light_cyan))
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.light_pink,
                                  'Confusion Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_chance < 90:
                    item_component = Item(use_function=str_increase, amount=1)
                    item = Entity(x,
                                  y,
                                  '!',
                                  libtcod.red,
                                  "Arok's Strength",
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                else:
                    item_component = Item(use_function=cast_lightning,
                                          damage=20,
                                          maximum_range=5)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.yellow,
                                  'Hustals Wrath',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                entities.append(item)
示例#7
0
    def main(self):
        # Game Loop
        while self.game_running:
            # Check input streams for an event
            libtcod.sys_check_for_event(
                libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, self.key,
                self.mouse)

            # If we need to recompute fov, do so
            if self.fov_recompute:
                recompute_fov(self.fov_map, self.player.x, self.player.y)

            # Render the game world according to current FOV, mark FOV recompute as complete, and flush to console
            render_all(self.con, self.panel, self.entities, self.player,
                       self.game_map, self.fov_map, self.fov_recompute,
                       self.message_log, self.mouse, self.game_state,
                       self.player_target)
            self.fov_recompute = False
            libtcod.console_flush()

            # Interpret the input into a game action
            input = handle_keys(self.key, self.game_state)
            action = input.get('action')

            inventory_item = input.get(
                'inventory_item') if 'inventory_item' in input else None
            dialogue_option = input.get(
                'dialogue_option') if 'dialogue_option' in input else None
            shop_option = input.get(
                'shop_option') if 'shop_option' in input else None
            unequip_item = input.get('slot') if 'slot' in input else None

            # If players turned and it's their turn to move
            if action == 'move' and self.game_state == GameStates.PLAYERS_TURN:
                # Calculate where they should move
                dx, dy = input.get('move')
                destination_x = self.player.x + dx
                destination_y = self.player.y + dy

                # TODO: This is where you hid the noclip check. Fix this for release
                #if not self.game_map.is_blocked(destination_x, destination_y):
                if True:
                    # If they're not about to walk into a wall, check for enemies at the destination
                    potential_collision_list = self.entities.get_sublist(
                        lambda ent: ent.x == destination_x and ent.y ==
                        destination_y and ent.blocks)
                    target = potential_collision_list[
                        0] if potential_collision_list else None
                    if target and target.state == AIStates.HOSTILE:
                        # If there are enemies, attack them
                        self.player.get_component("Fighter").attack(target)
                        self.game_state = GameStates.ENEMY_TURN
                    elif target and target.state == AIStates.FRIENDLY:
                        self.previous_game_state = self.game_state
                        self.player_target = target
                        self.game_state = GameStates.DIALOGUE
                    else:
                        # If there are not enemies, move and mark FOV for recomputation
                        self.player.move(dx, dy, self.game_map)
                        self.fov_recompute = True
                        self.game_map.compute_dijkstra_map([self.player],
                                                           'player', True)
                        self.game_state = GameStates.ENEMY_TURN

            # If the player grabs something, check if there is an object at their feet, and either have them pick it up (if it's an Item) or add it to their wallet (if it's money)
            elif action == 'grab' and self.game_state == GameStates.PLAYERS_TURN:
                for item in self.entities.get_sublist(
                        lambda entity: (entity.has_component("Item") or entity.
                                        has_component("Money")) and entity.x ==
                        self.player.x and entity.y == self.player.y):
                    if item.has_component("Money"):
                        self.player.get_component("Fighter").pick_up_money(
                            item)
                    else:
                        self.player.get_component("Inventory").add_item(item)
                    self.entities.remove_entity(item)
                    self.game_state = GameStates.ENEMY_TURN

            # Open up the inventory menu
            elif action == 'inventory' and inventory_item is None:
                self.previous_game_state = self.game_state
                self.game_state = GameStates.INVENTORY_OPEN

            # Open up the equipped menu
            elif action == 'equipped':
                self.previous_game_state = self.game_state
                self.game_state = GameStates.EQUIPPED_OPEN

            elif action == 'unequip' and self.game_state == GameStates.EQUIPPED_OPEN:
                self.player.get_component("Inventory").unequip_slot(
                    unequip_item)

            # if the player has selected an inventory item to use, get the item object, and equip it if it's vgear, or use it if it's a consumable (like a potion)
            elif inventory_item is not None and self.previous_game_state != GameStates.PLAYER_DEAD and inventory_item < len(
                    self.player.get_component("Inventory").items):
                item_entity = self.player.get_component(
                    "Inventory").items[inventory_item]
                if ItemType(item_entity.get_component(
                        "Item").item_type) != ItemType.NONE:
                    self.player.get_component("Inventory").equip_item(
                        item_entity)
                else:
                    print("In the else")
                    if item_entity.get_component("Item").use(self.player):
                        self.player.get_component("Inventory").remove_item(
                            item_entity)

            # if the player is in dialogue, provide the dialogue option to the target's Character object
            elif dialogue_option is not None:
                dialogue_response = self.player_target.get_component(
                    "Character").talk(dialogue_option)
                if dialogue_response.shop:
                    self.game_state = GameStates.SHOPPING

            # if the player attempts to go down some stairs, make sure they're on stairs, then build a new map and clear the console
            elif action == 'go_down' and self.game_state == GameStates.PLAYERS_TURN:
                stairs_candidates = self.entities.get_sublist(
                    lambda entity: entity.x == self.player.x and entity.y ==
                    self.player.y and entity.has_component("Stairs"))
                if stairs_candidates:
                    self.build_map(
                        stairs_candidates[0].get_component("Stairs").floor)
                    libtcod.console_clear(self.con)

            # Save the game
            elif action == 'save':
                save_game(self.player, self.entities, self.game_map,
                          self.message_log, self.game_state)

            # if the player draws their gun, change to a player shoot state and await gunfire
            elif self.game_state == GameStates.PLAYERS_TURN and action == 'gun':
                if (self.player.get_component("Inventory").slot_filled(
                        "RANGED")):
                    self.previous_game_state = self.game_state
                    self.game_state = GameStates.PLAYER_SHOOT
                    self.message_log.add_message(
                        Message(
                            "Taking aim. Click on your target, or e to holster"
                        ))
                else:
                    self.message_log.add_message(
                        Message("No ranged weapon equipped!"))

            # if the player already has their gun drawn and presses the draw button, holster it instead
            elif self.game_state == GameStates.PLAYER_SHOOT and action == 'holster':
                self.game_state = self.previous_game_state
                self.message_log.add_message(Message("Holstered your weapon"))

            # if the player has their gun drawn and clicks on a target, check if there is line of sight
            # and if so, shoot the target. This sets the AI to hostile if it isn't already (this should be handled by Fighter)
            elif self.game_state == GameStates.PLAYER_SHOOT and self.mouse.lbutton_pressed:
                target = get_shoot_target(self.mouse, self.entities,
                                          self.fov_map)
                if (target):
                    line_of_sight = draw_line((self.player.x, self.player.y),
                                              (target.x, target.y))
                    if not [
                            space for space in line_of_sight
                            if self.game_map.is_blocked(space[0], space[1])
                    ]:
                        self.player.get_component("Fighter").ranged_attack(
                            target)
                        target.state = AIStates.HOSTILE
                        self.game_state = GameStates.ENEMY_TURN
                    else:
                        self.message_log.add_message(
                            Message("You don't have a clear line of sight!"))

            # if the player right clicks something, get open up the inspect menu for that target
            elif self.mouse.rbutton_pressed and self.game_state != GameStates.INSPECT_OPEN:
                target = get_shoot_target(self.mouse, self.entities,
                                          self.fov_map, False)
                if (target):
                    self.player_target = target
                    self.previous_game_state = self.game_state
                    self.game_state = GameStates.INSPECT_OPEN

            # If the player is buying something, they make the purchase
            elif action == 'buy' and shop_option is not None:
                target.get_component("Shop").purchase(shop_option, self.player)

            elif action == 'status':
                self.previous_game_state = self.game_state
                self.game_state = GameStates.STATUS

            # Exit the game
            if action == 'exit' and (self.game_state in [
                    GameStates.INVENTORY_OPEN, GameStates.DIALOGUE,
                    GameStates.EQUIPPED_OPEN, GameStates.SHOPPING,
                    GameStates.INSPECT_OPEN, GameStates.STATUS
            ]):
                self.game_state = self.previous_game_state
            elif action == 'exit':
                return True

            # Set the game to fullscreen
            if action == 'fullscreen':
                libtcod.console_set_fullscreen(
                    not libtcod.console_is_fullscreen())

            # cull_dead returns true if the player is dead, so this conditional calls it to cull the dead, and then
            # checks if the game is over
            if self.cull_dead():
                self.game_state = GameStates.PLAYER_DEAD

            # when it's the AI's turn, find every entity that has AI and move it (if it's hostile)
            if self.game_state == GameStates.ENEMY_TURN:
                for entity in self.entities.get_entity_set():
                    if entity.has_component(
                            "AI") and entity.state == AIStates.HOSTILE:
                        entity.get_component("AI").take_turn(
                            self.player, self.fov_map, self.game_map,
                            self.entities)
                        if self.cull_dead():
                            self.game_state = GameStates.PLAYER_DEAD
                    if entity.has_component("StatusContainer"):
                        entity.get_component("StatusContainer").tick_clocks()
                        for status in entity.get_component(
                                "StatusContainer").get_statuses():
                            status_mapping[status](entity, self.entities,
                                                   self.game_map)

                if self.game_state != GameStates.PLAYER_DEAD:
                    self.player.get_component("StatusContainer").tick_clocks()
                    for status in self.player.get_component(
                            "StatusContainer").get_statuses():
                        status_mapping[status](self.player, self.entities,
                                               self.game_map)
                    self.game_map.compute_dijkstra_map(
                        self.entities.get_sublist(
                            lambda x: x.name != "Ascetic"), "enemies")
                    self.game_state = GameStates.PLAYERS_TURN

            # TODO: need a check somewhere around here to tick condition clocks, and then to apply conditions

            if action == 'restart':
                libtcod.console_clear(self.con)
                self.initialize_game()
示例#8
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    fov_map = initialize_fov(game_map)

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

    if not game_state == GameStates.PLAYER_DEAD:
        game_state = GameStates.PLAYERS_TURN

    previous_game_state = game_state

    targeting_item = None

    if not game_state == GameStates.PLAYER_DEAD:
        PLAYERDEADSTATE = False
    else:
        PLAYERDEADSTATE = True

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.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, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'], mouse,
                   constants['colors'], game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

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

        move = action.get('move')
        wait = action.get('wait')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        show_equipment_inventory = action.get('show_equipment_inventory')
        show_bag = action.get('show_bag')
        inventory_index = action.get('inventory_index')
        equipment_inventory_index = action.get('equipment_inventory_index')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        show_help_menu = action.get('show_help_menu')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')
        cast_magic_wand = action.get('cast_magic_wand')

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

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_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.PLAYERS_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

                elif entity.equipment_item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.equipment_inventory.add_equipment_item(
                        entity)
                    player_turn_results.extend(pickup_results)

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

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if show_equipment_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_EQUIPMENT_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if show_bag:
            previous_game_state = game_state
            game_state = GameStates.SHOW_BAG

        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 equipment_inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and equipment_inventory_index < len(
                player.equipment_inventory.equipment_items):
            equipment_item = player.equipment_inventory.equipment_items[
                equipment_inventory_index]
            player_turn_results.extend(
                player.equipment_inventory.use_equipment(equipment_item))

        if take_stairs and game_state == GameStates.PLAYERS_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 = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_clear(con)

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

        if cast_magic_wand and game_state == GameStates.PLAYERS_TURN:
            wand = player.inventory.search("Magic Wand")
            if wand is None:
                message_log.add_message(
                    Message("You do not have a magic wand.", libtcod.orange))
            else:
                player_turn_results.extend(
                    player.inventory.use(wand,
                                         entities=entities,
                                         fov_map=fov_map))

                game_state = GameStates.ENEMY_TURN

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.base_power += 1
            elif level_up == 'def':
                player.fighter.base_defense += 1
            elif level_up == 'mgc':
                player.fighter.base_magic += 1

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if show_help_menu:
            previous_game_state = game_state
            game_state = GameStates.HELP_MENU

        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,
                              GameStates.HELP_MENU,
                              GameStates.SHOW_EQUIPMENT_INVENTORY):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            elif game_state == GameStates.SHOW_BAG:
                if PLAYERDEADSTATE == True:
                    game_state = GameStates.PLAYER_DEAD
                else:
                    game_state = GameStates.PLAYERS_TURN
            else:
                save_game(player, entities, game_map, message_log, game_state)

                return True

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

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            equipment_item_added = player_turn_result.get(
                'equipment_item_added')
            item_consumed = player_turn_result.get('consumed')
            equipment_consumed = player_turn_result.get('equipment_consumed')
            item_dropped = player_turn_result.get('item_dropped')
            staff_used = player_turn_result.get('staff_used')
            equip = player_turn_result.get('equip')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_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 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) + "!",
                            libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

            if dead_entity:
                if dead_entity == player:
                    PLAYERDEADSTATE = True
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity, player)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if equipment_item_added:
                entities.remove(equipment_item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if equipment_consumed:
                game_state = GameStates.ENEMY_TURN

            if staff_used:
                game_state = GameStates.ENEMY_TURN

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

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

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

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_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 dequipped the {0}".format(
                                dequipped.name)))

                game_state = GameStates.ENEMY_TURN

        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 enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:

                            if dead_entity == player:
                                PLAYERDEADSTATE = True
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity, player)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break
                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
示例#9
0
def place_entities(room, entities, dungeon_level, colors):
    # get random number of monsters
    max_monsters_per_room = from_dungeon_level(
        [[1, 1], [2, 2], [3, 4], [5, 6]], dungeon_level)
    max_items_per_room = from_dungeon_level([[1, 1], [2, 4]], dungeon_level)

    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([[5, 3], [30, 5], [60, 7]], dungeon_level)
    }
    item_chances = {
        'healing_potion': 35,
        'sword': from_dungeon_level([[5, 4]], dungeon_level),
        'shield': from_dungeon_level([[15, 8]], dungeon_level),
        'lightning_scroll': from_dungeon_level([[25, 4]], dungeon_level),
        'fireball_scroll': from_dungeon_level([[25, 6]], dungeon_level),
        'confusion_scroll': from_dungeon_level([[10, 2]], dungeon_level)
    }

    for i in range(number_of_monsters):
        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',
                                 colors.get('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',
                                 colors.get('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_chance = random_choice_from_dict(item_chances)

            if item_chance == 'healing_potion':
                item_component = Item(use_function=heal, amount=40)
                item = Entity(x,
                              y,
                              '!',
                              colors.get('violet'),
                              'Healing Potion',
                              render_order=RenderOrder.ITEM,
                              item=item_component)
            elif item_chance == 'sword':
                equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                                  power_bonus=3)
                item = Entity(x,
                              y,
                              '/',
                              colors.get('sky'),
                              'Sword',
                              equippable=equippable_component)
            elif item_chance == 'shield':
                equippable_component = Equippable(EquipmentSlots.OFF_HAND,
                                                  defense_bonus=1)
                item = Entity(x,
                              y,
                              '[',
                              colors.get('darker_orange'),
                              'Shield',
                              equippable=equippable_component)
            elif item_chance == 'fireball_scroll':
                item_component = Item(
                    use_function=cast_fireball,
                    targeting=True,
                    targeting_message=Message(
                        'Left-click a target, or right click to cancel.',
                        colors.get('light_cyan')),
                    damage=25,
                    radius=3)
                item = Entity(x,
                              y,
                              '#',
                              colors.get('red'),
                              'Fireball Scroll',
                              render_order=RenderOrder.ITEM,
                              item=item_component)
            elif item_chance == 'confusion_scroll':
                item_component = Item(
                    use_function=cast_confuse,
                    targeting=True,
                    targeting_message=Message(
                        'Left-click a target, or right click to cancel.',
                        colors.get('light_cyan')))
                item = Entity(x,
                              y,
                              '#',
                              colors.get('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,
                              '#',
                              colors.get('yellow'),
                              'Lightning Scroll',
                              render_order=RenderOrder.ITEM,
                              item=item_component)
            entities.append(item)
示例#10
0
def kill_player(player):
    player.char = '%'
    player.color = Colors.DARK_RED
    player.name = 'A hero formerly known as ' + player.name

    return Message('YOU DIED!', Colors.LIGHT_RED), GameStates.PLAYER_DEAD
示例#11
0
def main():
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43

    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3
    max_items_per_room = 2

    colors = {
        'dark_wall': libtcod.Color(0, 0, 100),
        'dark_ground': libtcod.Color(50, 50, 150),
        'light_wall': libtcod.Color(130, 110, 50),
        'light_ground': libtcod.Color(200, 180, 50),
    }

    fighter_component = Fighter(hp=30, defense=2, power=5)
    inventory_component = Inventory(26)
    player = Entity(
        0,
        0,
        '@',
        libtcod.white,
        'Player',
        blocks=True,
        render_order=RenderOrder.ACTOR,
        fighter=fighter_component,
        inventory=inventory_component,
    )
    entities = [player]

    game_title = '7DRLC'

    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GRAYSCALE | libtcod.FONT_LAYOUT_TCOD)

    libtcod.console_init_root(screen_width, screen_height, game_title, False)

    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(
        max_rooms,
        room_min_size,
        room_max_size,
        map_width,
        map_height,
        player,
        entities,
        max_monsters_per_room,
        max_items_per_room,
    )

    fov_recompute = True

    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

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

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

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

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(
            con,
            panel,
            entities,
            player,
            game_map,
            fov_map,
            fov_recompute,
            message_log,
            screen_width,
            screen_height,
            bar_width,
            panel_height,
            panel_y,
            mouse,
            colors,
            game_state,
        )

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key, game_state)

        move = action.get('move')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        inventory_index = action.get('inventory_index')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_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 pickup and game_state == GameStates.PLAYERS_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.',
                                libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_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]
            print(item)

        if exit:
            if game_state == GameStates.SHOW_INVENTORY:
                game_state = previous_game_state
            else:
                return True

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

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

        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 enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_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_monster(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.PLAYERS_TURN
示例#12
0
def kill_player(player):
    player.char = '%'
    player.color = libtcod.dark_red
    playsound('player_death.wav')

    return Message('You died!', libtcod.red), GameStates.PLAYER_DEAD
示例#13
0
def play_game(player, entities, game_map, message_log, game_state, con,
            panel, constants):
    '''
    Main engine and executor of code
    '''
    fov_recompute = True

    fov_map = initialize_fov(game_map)

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

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():

        if game_map.dungeon_level == 51:
            end_game(player)

        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS |
            libtcod.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, entities, player, game_map, fov_map, fov_recompute,
                message_log, constants['screen_width'], constants['screen_height'],
                constants['bar_width'], constants['panel_height'],
                constants['panel_y'], mouse, constants['colors'], game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

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

        # checks for actions
        move = action.get('move')
        wait = action.get('wait')
        pickup = action.get('pickup')
        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_character_screen')
        show_rules_screen = action.get('show_rules_screen')
        shop = action.get('shop')
        shop_sell = action.get('shop_sell')
        shop_buy = action.get('shop_buy')
        sell_index = action.get('sell_index')
        buy_index = action.get('buy_index')
        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 = []

        # player moving
        if move and game_state == GameStates.PLAYERS_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

        # player waiting
        elif wait:
            game_state = GameStates.ENEMY_TURN

        # player tries to pick up item
        elif pickup and game_state == GameStates.PLAYERS_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.',
                        libtcod.yellow))

        # player shows inventory menu
        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        # player shows inventory menu
        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        # player selects object from 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))

        # player tries to take stairs
        if take_stairs and game_state == GameStates.PLAYERS_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 = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_clear(con)

                    break
            else:
                message_log.add_message(Message('There are no stairs here.',
                    libtcod.yellow))
        # player levels up
        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.base_power += 1
            elif level_up == 'def':
                player.fighter.base_defense += 1

            game_state = previous_game_state

        # player opens character screen
        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        # player opens rules screen
        if show_rules_screen:
            previous_game_state = game_state
            game_state = GameStates.RULES

        # player tries to target
        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})

        # player tries to enter shop
        if shop and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.shopkeep and entity.x == player.x and entity.y == player.y:
                    previous_game_state = game_state
                    game_state = GameStates.ENTER_SHOP

                    break
            else:
                message_log.add_message(Message('There is no shopkeeper here.',
                    libtcod.yellow))

        # player tries to sell
        if shop_sell:
            game_state = GameStates.SELLING

        # player tries to sell item at shop
        if sell_index is not None and previous_game_state != GameStates.PLAYER_DEAD and\
                game_state == GameStates.SELLING and sell_index < len(player.inventory.items):

            for entity in entities:
                if entity.shopkeep:
                    item_cost = player.inventory.items[sell_index].cashable.coin
                    player.fighter.coin += (item_cost // 10)
                    message_log.add_message(Message('You sell {0}for {1} coins.'\
                        .format(player.inventory.items[sell_index].name.split('(')[0],
                        (item_cost // 10)), libtcod.blue))
                    player.inventory.remove_item(player.inventory.items[sell_index])

                    break

        # player tries to buy
        if shop_buy:
            game_state = GameStates.BUYING

        # player tries to buy item at shop
        if buy_index is not None and previous_game_state != GameStates.PLAYER_DEAD and\
                game_state == GameStates.BUYING and buy_index < 25:

            for entity in entities:
                if entity.shopkeep:
                    player_coin = player.fighter.coin
                    item_cost = entity.inventory.items[buy_index].cashable.coin
                    if player_coin >= item_cost:
                        player.inventory.add_item(entity.inventory.items[buy_index])
                        player.fighter.coin -= item_cost
                        message_log.add_message(Message('You buy {0}for {1} coins.'\
                            .format(entity.inventory.items[buy_index].name.split('(')[0],
                            item_cost), libtcod.blue))
                    else:
                        message_log.add_message(Message('Not enough coins!',
                            libtcod.yellow))

                    break

        # exit menu or game
        if exit:
            if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY,
                    GameStates.CHARACTER_SCREEN, GameStates.RULES):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            elif game_state == GameStates.ENTER_SHOP:
                game_state = GameStates.PLAYERS_TURN
            elif game_state in (GameStates.SELLING, GameStates.BUYING):
                game_state = GameStates.ENTER_SHOP
            else:
                save_game(player, entities, game_map, message_log, game_state)

                return True

        # toggle fullscreen
        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        # player turn results
        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            equip = player_turn_result.get('equip')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_result.get('xp')
            coin = player_turn_result.get('coin')

            # adds message to log
            if message:
                message_log.add_message(message)

            # deals with dead entity
            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            # item picked up
            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            # item used
            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            # item dropped
            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            # item equip toggled
            if equip:
                equip_results = player.equipment.toggle_equip(equip)

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

                    if equipped:
                        message_log.add_message(Message('You equipped the {0}'\
                            .format(equipped.name.split('(')[0])))

                    if dequipped:
                        message_log.add_message(Message('You dequipped the {0}'\
                            .format(dequipped.name.split('(')[0])))

                game_state = GameStates.ENEMY_TURN

            # something targeted
            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            # targeting cancelled
            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))

            # gained xp
            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(Message('You gain {0} experience points.'\
                    .format(xp), libtcod.orange))

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

            # gained coins
            if coin:
                player.fighter.add_coin(coin)
                message_log.add_message(Message('You gain {0} coins.'\
                    .format(coin), libtcod.orange))
        # enemy takes turn
        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 enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        # adds message to log
                        if message:
                            message_log.add_message(message)

                        # checks for dead entity
                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            # if player is dead, we're done
                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    # if player is dead, we're done
                    if game_state == GameStates.PLAYER_DEAD:
                        break
            # player's turn again
            else:
                game_state = GameStates.PLAYERS_TURN
示例#14
0
文件: engine.py 项目: QuinceP/sprl
def play_game():
    screen_width = 70
    screen_height = 45

    bar_width = 20

    panel_horiz_height = 10
    panel_horiz_y = screen_height - panel_horiz_height
    panel_horiz = libtcod.console_new(screen_width, panel_horiz_height)

    panel_vert_height = panel_horiz_y
    panel_vert_y = 0
    panel_vert = libtcod.console_new(48, panel_vert_height)

    message_x = 1
    message_width = screen_width - 1
    message_height = panel_horiz_height - 2

    map_width = 47
    map_height = panel_horiz_y

    room_max_size = 8
    room_min_size = 3
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3
    max_items_per_room = 2

    colors = {
        'dark_wall': libtcod.Color(0, 0, 100),
        'dark_ground': libtcod.Color(50, 50, 150),
        'light_wall': libtcod.Color(130, 110, 50),
        'light_ground': libtcod.Color(200, 180, 50)
    }

    fighter_component = Fighter(hp=100, defense=1, power=2)
    inventory_component = Inventory(26)
    level_component = Level()
    equipment_component = Equipment()

    player = Entity(0, 0, '@', libtcod.white, 'Player', blocks=True, render_order=RenderOrder.ACTOR,
                    fighter=fighter_component, inventory=inventory_component, level=level_component,
                    equipment=equipment_component)

    entities = [player]

    equippable_component = Equippable(EquipmentSlots.MAIN_HAND, power_bonus=2)
    dagger = Entity(0, 0, '-', libtcod.sky, 'Dagger', equippable=equippable_component)
    player.inventory.add_item(dagger)
    player.equipment.toggle_equip(dagger)

    libtcod.console_set_custom_font(consts.FONT, libtcod.FONT_LAYOUT_ASCII_INROW)

    libtcod.console_init_root(screen_width, screen_height, 'libtcod tutorial revised', False)

    con = libtcod.console_new(screen_width, screen_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width, map_height, player, entities)

    fov_recompute = True

    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

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

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

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

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius, fov_light_walls, fov_algorithm)

        render_all(con, panel_vert, panel_horiz, entities, player, game_map, fov_map, fov_recompute, message_log,
                   screen_width, screen_height,
                   bar_width, panel_horiz_height, panel_horiz_y, panel_vert_height, panel_vert_y, mouse, colors,
                   game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

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

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

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

        player_turn_results = []

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

            if not game_map.is_blocked(player.x + dx, 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:
            message_log.add_message(Message('You wait for a moment.', libtcod.yellow))
            game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_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.', libtcod.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.PLAYERS_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, max_rooms, room_min_size, room_max_size,
                                                   map_width, map_height)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_clear(con)

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

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                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:
                return True

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

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

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(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 targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))

            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) + '!', libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

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

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_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 dequipped the {0}'.format(dequipped.name)))

                game_state = GameStates.ENEMY_TURN

        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 enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_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_monster(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.PLAYERS_TURN
示例#15
0
def main():
    constants = get_constants()

    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    libtcod.console_init_root(constants['screen_width'],
                              constants['screen_height'],
                              constants['window_title'], False)

    con = libtcod.console_new(constants['screen_width'],
                              constants['screen_height'])
    panel = libtcod.console_new(constants['screen_width'],
                                constants['panel_height'])

    player, entities, game_map, message_log, game_state = get_game_variables(
        constants)

    fov_recompute = True
    fov_map = initialize_fov(game_map)

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

    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.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, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'], mouse,
                   constants['colors'], game_state)

        fov_recompute = False

        libtcod.console_flush()
        clear_all(con, entities)

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

        move = action.get('move')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        inventory_index = action.get('inventory_index')
        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.PLAYERS_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 and target != player:  #if move(0,0) player would attack itself
                    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 pickup and game_state == GameStates.PLAYERS_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.',
                            libtcod.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 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):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                return True

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

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

            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_monster(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 targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

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

        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 enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_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_monster(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.PLAYERS_TURN
示例#16
0
def main():
    # Needed Variables
    screen_width = 80
    screen_height = 50
    map_width = 80
    map_height = 43

    # health bar
    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    # rooms
    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    # fov
    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    # monsters
    max_monsters_per_room = 3

    # items
    max_items_per_room = 10

    # message log
    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    colors = {
        'dark_wall': libtcod.Color(0, 0, 100),
        'dark_ground': libtcod.Color(50, 50, 150),
        'light_wall': libtcod.Color(130, 110, 50),
        'light_ground': libtcod.Color(200, 180, 50)
    }

    fighter_component = Fighter(hp=30, defense=2, power=5)
    inventory_component = Inventory(26)
    player = Entity(0,
                    0,
                    '@',
                    libtcod.white,
                    'Player',
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component,
                    inventory=inventory_component)
    entities = [player]

    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    # Creates initial console
    libtcod.console_init_root(screen_width, screen_height,
                              'libtcod tutorial revised', False)

    # Sets default console to draw to.
    console = libtcod.console_new(screen_width, screen_height)
    # hp panel console
    panel = libtcod.console_new(screen_width, panel_height)

    # Creates game map, draws rooms, populates them with monsters and items
    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room,
                      max_items_per_room)

    fov_recompute = True
    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

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

    game_state = GameStates.PLAYERS_TURN
    # Tracks the old game state, used when opening menus
    previous_game_state = game_state

    targeting_item = None

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

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(console, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors, game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(console, entities)

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

        # Player actions
        move = action.get('move')
        pickup = action.get('pickup')
        # Inventory actions
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        # Used when interacting with inventory
        inventory_index = action.get('inventory_index')
        # Out of game actions, do not take a turn
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')
        # Mouse clicks
        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_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 pickup and game_state == GameStates.PLAYERS_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.',
                            libtcod.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 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):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                return True

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

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

            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_monster(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 targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

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

        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 enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_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_monster(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.PLAYERS_TURN
示例#17
0
    def place_entities(self, room: Rect):
        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)

        number_of_monsters = randint(0, max_monsters_per_room)
        number_of_items = randint(0, max_items_per_room)

        with open("items.json", mode='r') as f:
            items_data = json.load(f)
            # print(items_data)
            items = [item for item in items_data["items"]]
            # for item in items:
            #     print(f'{item["id"]} {item["chance"]}')
            item_chances = {item["id"]: from_dungeon_level([item["chance"]], self.dungeon_level) for item in items}

        monster_chances = {
            "orc": 80,
            "troll": from_dungeon_level([[15, 3], [30, 5], [60, 7]], 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 self.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("Orc", EntityType.ACTOR, x, y, ord('o'), tcod.desaturated_green, blocks=True,
                                     fighter=fighter_component, ai=ai_component)
                else:
                    fighter_component = Fighter(hp=30, defense=2, power=8, xp=100)
                    ai_component = BasicMonster()
                    monster = Entity("Troll", EntityType.ACTOR, x, y, ord('T'), tcod.darker_green, blocks=True,
                                     fighter=fighter_component, ai=ai_component)

                self.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 self.entities if entity.x == x and entity.y == y]):
                item_choice = random_choice_from_dict(item_chances)
                chosen_item = None
                for item in items_data["items"]:
                    if item["id"] == item_choice:
                        if item["targeting_message"]:
                            targeting_message = Message(item["targeting_message"]["text"],
                                                        item["targeting_message"]["color"])
                        else:
                            targeting_message = None

                        if item["use_function"]:
                            use_function = eval(item["use_function"])
                        else:
                            use_function = None

                        if item["function_kwargs"]:
                            item_component = Item(use_function=use_function, targeting=item["targeting"],
                                                  targeting_message=targeting_message, **item["function_kwargs"])
                        else:
                            item_component = Item(use_function=use_function, targeting=item["targeting"],
                                                  targeting_message=targeting_message)

                        if item["equippable"]:
                            equippable_component = Equippable(EquipmentSlots(item["equippable"]["slot"]),
                                                              power_bonus=item["equippable"]["power_bonus"],
                                                              defense_bonus=item["equippable"]["defense_bonus"],
                                                              max_hp_bonus=item["equippable"]["max_hp_bonus"])
                        else:
                            equippable_component = None

                        chosen_item = Entity(item["name"], EntityType.ITEM, x, y, ord(item["glyph"]), fg=item["color"],
                                             item=item_component, equippable=equippable_component)
                # if item_choice == "healing_potion":
                #     item_component = Item(use_function=heal, amount=40)
                #     item = Entity("Healing Potion", EntityType.ITEM, x, y, ord('!'), fg=tcod.violet,
                #                   item=item_component)
                # elif item_choice == "sword":
                #     equippable_component = Equippable(EquipmentSlots.MAIN_HAND, power_bonus=3)
                #     item = Entity("Sword", EntityType.ITEM, x, y, ord('/'), fg=tcod.sky,
                #                   equippable=equippable_component)
                # elif item_choice == "shield":
                #     equippable_component = Equippable(EquipmentSlots.OFF_HAND, defense_bonus=1)
                #     item = Entity("Shield", EntityType.ITEM, x, y, ord('['), fg=tcod.darker_orange,
                #                   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("Fireball Scroll", EntityType.ITEM, x, y, ord('#'), fg=tcod.orange,
                #                   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("Confusion Scroll", EntityType.ITEM, x, y, ord('#'), fg=tcod.light_pink,
                #                   item=item_component)
                # else:
                #     item_component = Item(use_function=cast_lightning, damage=40, maximum_range=5)
                #     item = Entity("Lightning Scroll", EntityType.ITEM, x, y, ord('#'), fg=tcod.yellow,
                #                   item=item_component)

                self.entities.append(chosen_item)
示例#18
0
    def attack(self, target):
        results = []

        if target.name == "Ghost":
            results.append({
                'message':
                Message(
                    "{0} attacks {1} but phases through it!".format(
                        self.owner.name.capitalize(), target.name),
                    libtcod.orange)
            })
        else:

            attack_chance = randint(1, 20)

            if self.owner.name == "Ghost":
                damage = round(self.magic *
                               (10 / (10 + target.fighter.magic_defense)))
            else:
                damage = round(self.power * (10 /
                                             (10 + target.fighter.defense)))

            if 2 <= attack_chance <= 19:
                if damage > 0:
                    results.append({
                        'message':
                        Message(
                            "{0} attacks {1} for {2} hit 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)
                    })
                    results.extend(target.fighter.take_damage(damage))

            elif attack_chance == 1:
                dodgemiss = randint(1, 2)

                if dodgemiss == 1:
                    results.append({
                        'message':
                        Message(
                            "{0} attacks {1} but {1} dodges!".format(
                                self.owner.name.capitalize(), target.name),
                            libtcod.white)
                    })
                else:
                    results.append({
                        'message':
                        Message(
                            "{0} attacks {1} but misses!".format(
                                self.owner.name.capitalize(), target.name),
                            libtcod.white)
                    })

            elif attack_chance == 20:

                damage = damage * 2

                results.append({
                    'message':
                    Message(
                        "{0} attacks {1} and critical hits for {2} hit points!"
                        .format(self.owner.name.capitalize(), target.name,
                                str(damage)), libtcod.white)
                })
                results.extend(target.fighter.take_damage(damage))

        return results
示例#19
0
 def send_invalid_action_message(self):
     self.message_log.add_message(Message("Can't do that here"),
                                  libtcod.red)
示例#20
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    fov_map = initialize_fov(game_map)

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

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.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, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'], mouse,
                   constants['colors'], game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

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

        move = action.get('move')
        wait = action.get('wait')
        pickup = action.get('pickup')
        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_character_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.PLAYERS_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.PLAYERS_TURN:
            for entity in entities.entity:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    if entity.name == 'pool of blud':
                        entities.remove_entity(entity)
                        message_log.add_message(
                            Message(
                                'You absorb the powerblud through your hands...',
                                libtcod.red))
                        player.fighter.blood += randint(2, 10)
                        if player.fighter.max_blood < player.fighter.blood:
                            message_log.add_message(
                                Message('You cannot contain that much blud!',
                                        libtcod.yellow))
                            if player.fighter.hp < player.fighter.max_hp:
                                message_log.add_message(
                                    Message(
                                        'You are healed by some of the escaping blud essence!',
                                        libtcod.yellow))
                                player.fighter.hp += randint(1, 5)
                            else:
                                message_log.add_message(
                                    Message(
                                        'The essence escapes into the Aether. What a waste.',
                                        libtcod.blue))
                                player.fighter.blood = player.fighter.max_blood
                    else:
                        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.',
                            libtcod.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))
                if item.material == 'glass':
                    equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                                      power_bonus=2)
                    item = Entity(player.x,
                                  player.y,
                                  '/',
                                  libtcod.sky,
                                  'Handfull of glass shards',
                                  equippable=equippable_component)
                    entities.add_new_entity(item)
                    message_log.add_message(
                        Message(
                            'The bottle shatters into a hundred pieces as you drop it.',
                            libtcod.blue))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

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

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

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                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:
                save_game(player, entities, game_map, message_log, game_state)

                return True

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

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

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)
                    item_component = Item(use_function=heal, amount=0)
                    item = Entity(dead_entity.x,
                                  dead_entity.y,
                                  '$',
                                  libtcod.red,
                                  'pool of blud',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                    entities.add_new_entity(item)

                message_log.add_message(message)

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

            if item_consumed:

                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.add_new_entity(item_dropped)

                game_state = GameStates.ENEMY_TURN

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

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_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 dequipped the {0}'.format(
                                dequipped.name)))

                game_state = GameStates.ENEMY_TURN

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

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))

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

                if leveled_up:

                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

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

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_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_monster(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.PLAYERS_TURN
    def place_entities(self, room, entities):
        max_monsters_per_room = from_dungeon_level([[2, 1], [4, 3], [6, 6]], self.dungeon_level)
        max_items_per_room = from_dungeon_level([[1, 1], [2, 4]], self.dungeon_level)

        number_of_monsters = randint(0, max_monsters_per_room)
        number_of_items = randint(0, max_items_per_room)


        monster_chances = {
            'risen_corpse': 60,
            'cultist': from_dungeon_level([[15, 2], [40, 4], [60, 6]], self.dungeon_level),
            'unholy_priest': from_dungeon_level([[10, 3], [20, 4], [30, 5], [50, 7]], self.dungeon_level),
            'shadowy_horror': from_dungeon_level([[1, 3], [5, 5], [10, 6]], self.dungeon_level),
        }

        item_chances = {
            'healing_potion': 50,
            'dull_sword': from_dungeon_level([[15, 2], [3, 4]], self.dungeon_level),
            'plain_shirt': from_dungeon_level([[5, 1], [10, 2], [3, 4]], self.dungeon_level),
            'sharpened_sword': from_dungeon_level([[7, 3], [12, 5]], self.dungeon_level),
            'battered_shield': from_dungeon_level([[15, 2], [3, 4]], self.dungeon_level),
            'hardened_shield': from_dungeon_level([[7, 3], [12, 5]], self.dungeon_level),
            'lost_pages': from_dungeon_level([[5, 4], [15, 6]], self.dungeon_level),
            'dirty_spectacles': from_dungeon_level([[1, 1], [2, 2], [7, 4]], self.dungeon_level),
            'rough_trousers': from_dungeon_level([[5, 3], [10, 5], [3, 4]], self.dungeon_level),
            'fine_shoes': from_dungeon_level([[1, 1], [3, 5]], self.dungeon_level),
            'lightning_scroll': from_dungeon_level([[15, 4], [20, 6]], self.dungeon_level),
            'fireball_scroll': from_dungeon_level([[15, 5], [20, 7]], self.dungeon_level),
            'confusion_scroll': from_dungeon_level([[10, 2], [15, 4]], self.dungeon_level),
            'fireball_tome': from_dungeon_level([[4, 4], [7, 5]], self.dungeon_level),
            'confusion_tome': from_dungeon_level([[4, 4], [7, 5]], self.dungeon_level),
            'eldritch_blast_tome': from_dungeon_level([[4, 4], [7, 5]], self.dungeon_level),
            'lightning_blast_tome': from_dungeon_level([[4, 4], [7, 5]], 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 == 'risen_corpse':
                    zombie_equipment = []
                    zombie_fighter_component = Fighter(hp=15, defense=0, strength=3, accuracy=85, dodge=0, ability_power=0, crit_chance=5, xp=35)
                    ai_component = BasicMonster()
                    enemy_inventory_component = Inventory(5)
                    enemy_equipment_component = Equipment()
                    enemy_info_component = Information('risen_corpse')

                    ragged_shoes_component = Equippable(EquipmentSlots.FEET, dodge_bonus=5, accuracy_bonus=5)
                    ragged_shoes_info_component = Information('ragged_shoes')
                    ragged_shoes_entity = Entity(0, 0, 's', libtcod.Color(125, 80, 12), 'Ragged Shoes',
                                            equippable=ragged_shoes_component, info=ragged_shoes_info_component)

                    torn_pants_component = Equippable(EquipmentSlots.LOWER_BODY, max_hp_bonus=10)
                    torn_pants_info_component = Information('torn_pants')
                    torn_pants_entity = Entity(0, 0, 'p', libtcod.Color(143, 73, 7), 'Torn Pants',
                                            equippable=torn_pants_component, info=torn_pants_info_component)

                    mystic_hood_component = Equippable(EquipmentSlots.HEAD, ability_power_bonus=1)
                    mystic_hood_info_component = Information('mystic_hood')
                    mystic_hood_entity = Entity(0, 0, '^', libtcod.Color(159, 71, 214), 'Mystic Hood',
                                            equippable=mystic_hood_component, info=mystic_hood_info_component)

                    broken_sword_component = Equippable(EquipmentSlots.MAIN_HAND, strength_bonus=1, crit_chance_bonus=3)
                    broken_sword_info_component = Information('broken_sword')
                    broken_sword_entity = Entity(0, 0, '-', libtcod.Color(219, 219, 219), 'Broken Sword',
                                            equippable=broken_sword_component, info=broken_sword_info_component)

                    zombie_equipment.append(ragged_shoes_entity)
                    zombie_equipment.append(torn_pants_entity)
                    zombie_equipment.append(mystic_hood_entity)
                    zombie_equipment.append(broken_sword_entity)

                    monster = Entity(x, y, 'z', libtcod.darkest_green, 'risen corpse', blocks=True,
                                     inventory=enemy_inventory_component, render_order=RenderOrder.ACTOR, fighter=zombie_fighter_component, ai=ai_component,
                                     equipment=enemy_equipment_component, info=enemy_info_component)

                    for equip in zombie_equipment:
                        if randint(1, 4) > 3:
                            monster.inventory.add_item(equip)
                            monster.equipment.toggle_equip(equip)
                    if monster.fighter.hp < monster.fighter.max_hp:
                        monster.fighter.heal(1000000)

                elif monster_choice == 'cultist':
                    fighter_component = Fighter(hp=20, defense=1, strength=5, accuracy=85, dodge=15, ability_power=0, crit_chance=10, xp=100)
                    ai_component = BasicMonster()
                    enemy_inventory_component = Inventory(5)
                    enemy_equipment_component = Equipment()
                    enemy_info_component = Information('cultist')

                    cultist_cloak_component = Equippable(EquipmentSlots.UPPER_BODY, dodge_bonus=5, max_hp_bonus=10)
                    cultist_cloak_info_component = Information('cultist_cloak')
                    cultist_cloak_entity = Entity(0, 0, '&', libtcod.Color(108, 12, 138), 'Cultist Cloak',
                                            equippable=cultist_cloak_component, info=cultist_cloak_info_component)

                    cultist_blade_component = Equippable(EquipmentSlots.MAIN_HAND, crit_chance_bonus=10, strength_bonus=2)
                    cultist_blade_info_component = Information('cultist_blade')
                    cultist_blade_entity = Entity(0, 0, '-', libtcod.Color(179, 179, 179), 'Cultist Blade',
                                            equippable=cultist_blade_component, info=cultist_blade_info_component)

                    monster = Entity(x, y, 'C', libtcod.Color(34, 3, 43), 'cultist', blocks=True, fighter=fighter_component,
                                     inventory=enemy_inventory_component, render_order=RenderOrder.ACTOR, ai=ai_component, equipment=enemy_equipment_component, info=enemy_info_component)

                    monster.inventory.add_item(cultist_cloak_entity)
                    monster.inventory.add_item(cultist_blade_entity)
                    monster.equipment.toggle_equip(cultist_cloak_entity)
                    monster.equipment.toggle_equip(cultist_blade_entity)

                    if monster.fighter.hp < monster.fighter.max_hp:
                        monster.fighter.heal(1000000)

                elif monster_choice == 'unholy_priest':
                    priest_fighter_component = Fighter(hp=40, defense=1, strength=2, accuracy=90, dodge=15, ability_power=0, crit_chance=5, xp=150)
                    ai_component = AbilityMonster()
                    enemy_inventory_component = Inventory(5)
                    enemy_equipment_component = Equipment()
                    enemey_abilities_component = Abilities(2)
                    enemy_info_component = Information('unholy_priest')

                    tattered_robe_component = Equippable(EquipmentSlots.UPPER_BODY, max_hp_bonus=10, dodge_bonus=10, defense_bonus=1)
                    tattered_robe_info_component = Information('tattered_robe')
                    tattered_robe_entity = Entity(0, 0, 'C', libtcod.Color(232, 216, 125), 'Tattered Robe',
                                            equippable=tattered_robe_component, info=tattered_robe_info_component)

                    corrupted_scripture_component = Equippable(EquipmentSlots.OFF_HAND, max_hp_bonus=-10, ability_power_bonus=5)
                    corrupted_scripture_info_component = Information('corrupted_scripture')
                    corrupted_scripture_entity = Entity(0, 0, '#', libtcod.Color(110, 0, 0), 'Corrupted Scripture',
                                            equippable=corrupted_scripture_component, info=corrupted_scripture_info_component)

                    monster = Entity(x, y, 'P', libtcod.Color(189, 169, 53), 'unholy priest', blocks=True, fighter=priest_fighter_component,
                                     inventory=enemy_inventory_component, abilities=enemey_abilities_component, render_order=RenderOrder.ACTOR,
                                     ai=ai_component, equipment=enemy_equipment_component, info=enemy_info_component)

                    eldritch_bolt = Feat(name="Eldritch Bolt", cooldown=3, damage=7, feat_function=cast_unholy_bolt_feat)

                    monster.abilities.add_feat([eldritch_bolt])
                    monster.inventory.add_item(corrupted_scripture_entity)
                    monster.inventory.add_item(tattered_robe_entity)
                    monster.equipment.toggle_equip(corrupted_scripture_entity)
                    monster.equipment.toggle_equip(tattered_robe_entity)

                elif monster_choice == 'shadowy_horror':
                    horror_fighter_component = Fighter(hp=75, defense=0, strength=2, accuracy=100, dodge=25, ability_power=0, crit_chance=25, xp=200)
                    ai_component = BasicMonster()
                    enemy_inventory_component = Inventory(5)
                    enemy_equipment_component = Equipment()
                    enemy_info_component = Information('shadowy_horror')

                    shadowy_hide_component = Equippable(EquipmentSlots.UPPER_BODY, dodge_bonus=15, defense_bonus=3)
                    shadowy_hide_info_component = Information('shadowy_hide')
                    shadowy_hide_entity = Entity(0, 0, 'h', libtcod.Color(0, 0, 0), 'shadowy hide',
                                            equippable=shadowy_hide_component, info=shadowy_hide_info_component)

                    shadowy_appendage_component = Equippable(EquipmentSlots.MAIN_HAND, strength_bonus=5, crit_chance_bonus=15)
                    shadowy_appendage_info_component = Information('shadowy_appendage')
                    shadowy_appendage_entity = Entity(0, 0, '|', libtcod.Color(0, 0, 0), 'shadowy appendage',
                                            equippable=shadowy_appendage_component, info=shadowy_appendage_info_component)

                    shadowy_mask_component = Equippable(EquipmentSlots.HEAD, accuracy_bonus=25, ability_power_bonus=10)
                    shadowy_mask_info_component = Information('shadowy_mask')
                    shadowy_mask_entity = Entity(0, 0, '|', libtcod.Color(0, 0, 0), 'shadowy mask',
                                            equippable=shadowy_mask_component, info=shadowy_mask_info_component)

                    monster = Entity(x, y, 'H', libtcod.Color(0, 0, 0), 'shadowy horror', blocks=True, fighter=horror_fighter_component,
                                     inventory=enemy_inventory_component, render_order=RenderOrder.ACTOR, ai=ai_component, equipment=enemy_equipment_component, info=enemy_info_component)

                    monster.inventory.add_item(shadowy_hide_entity)
                    monster.inventory.add_item(shadowy_appendage_entity)
                    monster.inventory.add_item(shadowy_mask_entity)
                    monster.equipment.toggle_equip(shadowy_hide_entity)
                    monster.equipment.toggle_equip(shadowy_appendage_entity)
                    monster.equipment.toggle_equip(shadowy_mask_entity)


                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':
                    hp_potion_item_component = Item(use_function=heal, amount=40)
                    hp_potion_info_component = Information('healing_potion')
                    item = Entity(x, y, '!', libtcod.violet, 'Healing Potion', render_order=RenderOrder.ITEM,
                                  item=hp_potion_item_component, info=hp_potion_info_component)
                elif item_choice == 'plain_shirt':
                    pshirt_equippable_component = Equippable(EquipmentSlots.UPPER_BODY, max_hp_bonus=15)
                    pshirt_info_component = Information('plain_shirt')
                    item = Entity(x, y, 'v', libtcod.white, 'Plain Shirt', render_order=RenderOrder.ITEM, equippable=pshirt_equippable_component,
                                  info=pshirt_info_component)
                elif item_choice == 'dull_sword':
                    dsword_equippable_component = Equippable(EquipmentSlots.MAIN_HAND, strength_bonus=2, crit_chance_bonus=5)
                    dsword_info_component = Information('dull_sword')
                    item = Entity(x, y, '/', libtcod.darkest_gray, 'Dull Sword', render_order=RenderOrder.ITEM, equippable=dsword_equippable_component,
                                  info=dsword_info_component)
                elif item_choice == 'sharpened_sword':
                    ssword_equippable_component = Equippable(EquipmentSlots.MAIN_HAND, strength_bonus=4, crit_chance_bonus=7)
                    ssword_info_component = Information('sharpened_sword')
                    item = Entity(x, y, '/', libtcod.lightest_gray, 'Sharpened Sword', render_order=RenderOrder.ITEM, equippable=ssword_equippable_component,
                                  info=ssword_info_component)
                elif item_choice == 'battered_shield':
                    bshield_equippable_component = Equippable(EquipmentSlots.OFF_HAND, max_hp_bonus=10, defense_bonus=1)
                    bshield_info_component = Information('battered_shield')
                    item = Entity(x, y, '[', libtcod.orange, 'Battered Shield', render_order=RenderOrder.ITEM, equippable=bshield_equippable_component,
                                  info=bshield_info_component)
                elif item_choice == 'hardened_shield':
                    hshield_equippable_component = Equippable(EquipmentSlots.OFF_HAND, max_hp_bonus=15, defense_bonus=2)
                    hshield_info_component = Information('hardened_shield')
                    item = Entity(x, y, '[', libtcod.darker_orange, 'Hardened Shield', render_order=RenderOrder.ITEM, equippable=hshield_equippable_component,
                                  info=hshield_info_component)
                elif item_choice == 'lost_pages':
                    lpages_equippable_component = Equippable(EquipmentSlots.OFF_HAND, ability_power_bonus=2, dodge_bonus=5)
                    lpages_info_component = Information('lost_pages')
                    item = Entity(x, y, '#', libtcod.light_sepia, 'Lost Pages', render_order=RenderOrder.ITEM, equippable=lpages_equippable_component,
                                  info=lpages_info_component)
                elif item_choice == 'dirty_spectacles':
                    dspecs_equippable_component = Equippable(EquipmentSlots.HEAD, accuracy_bonus=10, crit_chance_bonus=10, ability_power_bonus=-1)
                    dspecs_info_component = Information('dirty_spectacles')
                    item = Entity(x, y, '8', libtcod.lightest_blue, 'Dirty Spectacles', render_order=RenderOrder.ITEM, equippable=dspecs_equippable_component,
                                  info=dspecs_info_component)
                elif item_choice == 'fine_shoes':
                    fshoes_equippable_component = Equippable(EquipmentSlots.FEET, dodge_bonus=10, accuracy_bonus=10)
                    fshoes_info_component = Information('fine_shoes')
                    item = Entity(x, y, 's', libtcod.Color(235, 190, 66), 'Fine Shoes', render_order=RenderOrder.ITEM, equippable=fshoes_equippable_component,
                                  info=fshoes_info_component)
                elif item_choice == 'rough_trousers':
                    rpants_equippable_component = Equippable(EquipmentSlots.LOWER_BODY, max_hp_bonus=15, defense_bonus=2, dodge_bonus=-10)
                    rpants_info_component = Information('rough_trousers')
                    item = Entity(x, y, 'p', libtcod.Color(237, 114, 19), 'Rough Trousers', render_order=RenderOrder.ITEM, equippable=rpants_equippable_component,
                                  info=rpants_info_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.', libtcod.light_cyan),
                                          damage=25, radius=3)
                    fireballsc_info_component = Information('fireball_scroll')
                    item = Entity(x, y, '#', libtcod.red, 'Fireball Scroll', render_order=RenderOrder.ITEM,
                                  item=item_component, info=fireballsc_info_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.', libtcod.light_cyan))
                    confusionsc_info_component = Information('confusion_scroll')
                    item = Entity(x, y, '#', libtcod.light_pink, 'Confusion Scroll', render_order=RenderOrder.ITEM,
                                  item=item_component, info=confusionsc_info_component)
                elif item_choice == 'lightning_scroll':
                    item_component = Item(use_function=cast_lightning, damage=40, maximum_range=5)
                    lightningsc_info_component = Information('lightning_scroll')
                    item = Entity(x, y, '#', libtcod.yellow, 'Lightning Scroll', render_order=RenderOrder.ITEM,
                                  item=item_component, info=lightningsc_info_component)
                elif item_choice == 'fireball_tome':
                    item_component = Item(use_function=add_fireball)
                    firetome_info_component = Information('fireball_tome')
                    item = Entity(x, y, 't', libtcod.red, 'Fireball Tome', render_order=RenderOrder.ITEM,
                                  item=item_component, info=firetome_info_component)
                elif item_choice == 'confusion_tome':
                    item_component = Item(use_function=add_confusion)
                    confusiontome_info_component = Information('confusion_tome')
                    item = Entity(x, y, 't', libtcod.lighter_pink, 'Confusion Tome', render_order=RenderOrder.ITEM,
                                  item=item_component, info=confusiontome_info_component)
                elif item_choice == 'eldritch_blast_tome':
                    item_component = Item(use_function=add_eldritch_blast)
                    ebtome_info_component = Information('eldritch_blast_tome')
                    item = Entity(x, y, 't', libtcod.Color(148, 103, 245), 'Eldritch Blast Tome', render_order=RenderOrder.ITEM,
                                  item=item_component, info=ebtome_info_component)
                elif item_choice == 'lightning_tome':
                    item_component = Item(use_function=add_lightning)
                    lighttome_info_component = Information('lightning_tome')
                    item = Entity(x, y, 't', libtcod.light_yellow, 'Lightning Bolt Tome', render_order=RenderOrder.ITEM,
                                  item=item_component, info=lighttome_info_component)
                else:
                    item_component = Item(use_function=junk)
                    junk_info_component = Information('junk')
                    item = Entity(x, y, 'j', libtcod.light_gray, 'Pile of Junk', render_order=RenderOrder.ITEM,
                                  item=item_component, info=junk_info_component)

                entities.append(item)
示例#22
0
    def place_entities(self, room, entities, max_monsters_per_room,
                       max_items_per_room):
        # Get a random number of monsters
        number_of_monster = randint(0, max_monsters_per_room)
        number_of_items = randint(0, max_items_per_room)

        for i in range(number_of_monster):
            # 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
            ]):
                if randint(0, 100) < 80:
                    fighter_component = Fighter(hp=10, defense=0, power=3)
                    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=16, defense=1, power=4)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     'T',
                                     tcod.darker_green,
                                     'Troll',
                                     blocks=True,
                                     fighter=fighter_component,
                                     render_order=RenderOrder.ACTOR,
                                     ai=ai_component)

                entities.append(monster)
        for i in range(number_of_monster):
            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 < 70:
                    item_component = Item(use_function=heal, amount=4)
                    item = Entity(x,
                                  y,
                                  '!',
                                  tcod.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.',
                            tcod.light_cyan),
                        damage=12,
                        radius=3)
                    item = Entity(x,
                                  y,
                                  "#",
                                  tcod.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.',
                            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=20,
                                          maximum_range=5)
                    item = Entity(x,
                                  y,
                                  '#',
                                  tcod.yellow,
                                  'Lightning Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)

                entities.append(item)
示例#23
0
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants):
    fov_recompute = True # do we need to recompute? only when we move

    fov_map = initialize_fov(game_map)

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

    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():
        # Capture key & mouse events
        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.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, entities, player, game_map, fov_map, fov_recompute, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], mouse, constants['colors'], game_state)
        
        fov_recompute = False

        libtcod.console_flush()
        clear_all(con, entities)

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

        move = action.get('move')
        wait = action.get('wait')
        pickup = action.get('pickup')
        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_character_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.PLAYERS_TURN:
            dx, dy = move
            dest_x, dest_y = player.x + dx, player.y + dy
            if not game_map.is_blocked(dest_x, dest_y):
                target = get_blocking_entities_at_location(entities, dest_x, dest_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.PLAYERS_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', libtcod.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.PLAYERS_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 = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_clear(con)

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

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                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:
                save_game(player, entities, game_map, message_log, game_state)
                return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.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 xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(Message(f'You gain {xp} xp.'))

                if leveled_up:
                    message_log.add_message(Message(
                        f"Your combat skills grow stronger! You've reached level {player.level.current_level}!", libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

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

            if item_added:
                entities.remove(item_added)
                game_state = GameStates.ENEMY_TURN
                # picking up takes your turn... TODO

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

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

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if item_dropped:
                entities.append(item_dropped)
                game_state = GameStates.ENEMY_TURN
                # Dropping an item takes your turn? TODO

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

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

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

                game_state = GameStates.ENEMY_TURN

        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_monster(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.PLAYERS_TURN
示例#24
0
def get_game_variables(constants):
    fighter_component = Fighter(hp=100,
                                defense=1,
                                power=2,
                                magic=0,
                                magic_defense=1,
                                talismanhp=0,
                                gold=0,
                                status=None,
                                mana=100)
    inventory_component = Inventory(26)
    equipment_inventory_component = Inventory(26)
    level_component = Level()
    equipment_component = Equipment()
    player = Entity(0,
                    0,
                    constants['player_tile'],
                    libtcod.white,
                    'Player',
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component,
                    inventory=inventory_component,
                    level=level_component,
                    equipment=equipment_component,
                    equipment_inventory=equipment_inventory_component)
    entities = [player]

    equipment_component = Equippable(EquipmentSlots.MAIN_HAND,
                                     power_bonus=1,
                                     gold=1)
    dagger = Entity(0,
                    0,
                    constants['dagger_tile'],
                    libtcod.white,
                    "Terrium Dagger (+1 atk)",
                    equippable=equipment_component)
    player.equipment_inventory.add_item(dagger)
    player.equipment.toggle_equip(dagger)

    item_component = Item(use_function=cast_magic,
                          damage=2,
                          maximum_range=3,
                          gold=2)
    magic_wand = Entity(0,
                        0,
                        constants['magic_wand_tile'],
                        libtcod.white,
                        "Magic Wand",
                        item=item_component)
    player.inventory.add_item(magic_wand)

    game_map = GameMap(constants['map_width'], constants['map_height'])
    game_map.make_map(
        constants['max_rooms'], constants['room_min_size'],
        constants['room_max_size'], constants['map_width'],
        constants['map_height'], player, entities, constants['orc_tile'],
        constants['healing_potion_tile'], constants['scroll_tile'],
        constants['troll_tile'], constants['stairs_tile'],
        constants['sword_tile'], constants['shield_tile'],
        constants['dagger_tile'], constants['magic_wand_tile'],
        constants['greater_healing_potion_tile'], constants['ghost_tile'],
        constants['slime_tile'], constants['corpse_tile'],
        constants['goblin_tile'], constants['baby_slime_tile'],
        constants['skeleton_tile'], constants['slime_corpse_tile'],
        constants['baby_slime_corpse_tile'], constants['skeleton_corpse_tile'],
        constants['mana_potion_tile'], constants['wizard_staff_tile'],
        constants['health_talisman_tile'], constants['basilisk_tile'],
        constants['treasure_tile'], constants['chestplate_tile'],
        constants['leg_armor_tile'], constants['helmet_tile'],
        constants['amulet_tile'], constants['floor_tile'],
        constants['long_bow_tile'], constants['arrow_tile'])

    item_descriptors = [
        'Valor', 'Power', 'Ingenuity', 'Glory', 'Strength', 'Speed', 'Wealth',
        'Divinity', 'Energy', 'Honor', 'Resistance', 'Greatness', 'Courage',
        'Intelligence'
    ]

    all_shop_equipment = []

    sword_amount = randint(2, 4)
    equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                      power_bonus=sword_amount,
                                      gold=10)
    item = Entity(0,
                  0,
                  constants['sword_tile'],
                  libtcod.white,
                  "Terrium Sword of " + random.choice(item_descriptors) +
                  " (+" + str(sword_amount) + " atk)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    shield_amount = randint(1, 2)
    equippable_component = Equippable(EquipmentSlots.OFF_HAND,
                                      defense_bonus=shield_amount,
                                      gold=7)
    item = Entity(0,
                  0,
                  constants['shield_tile'],
                  libtcod.white,
                  "Terrium Shield of " + random.choice(item_descriptors) +
                  " (+" + str(shield_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    chestplate_amount = randint(2, 3)
    equippable_component = Equippable(EquipmentSlots.CHEST,
                                      defense_bonus=chestplate_amount,
                                      gold=20)
    item = Entity(0,
                  0,
                  constants['chestplate_tile'],
                  libtcod.darker_grey,
                  "Terrium Chestplate of " + random.choice(item_descriptors) +
                  " (+" + str(chestplate_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    leg_amount = randint(1, 3)
    equippable_component = Equippable(EquipmentSlots.LEGS,
                                      defense_bonus=leg_amount,
                                      gold=15)
    item = Entity(0,
                  0,
                  constants['leg_armor_tile'],
                  libtcod.darker_grey,
                  "Terrium Leg Armor of " + random.choice(item_descriptors) +
                  " (+" + str(leg_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    helmet_amount = randint(1, 2)
    equippable_component = Equippable(EquipmentSlots.HEAD,
                                      defense_bonus=helmet_amount,
                                      gold=5)
    item = Entity(0,
                  0,
                  constants['helmet_tile'],
                  libtcod.darker_grey,
                  "Terrium Helmet of " + random.choice(item_descriptors) +
                  " (+" + str(helmet_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    amulet_amount = randint(1, 4)
    equippable_component = Equippable(EquipmentSlots.AMULET,
                                      magic_bonus=amulet_amount,
                                      gold=6)
    item = Entity(0,
                  0,
                  constants['amulet_tile'],
                  libtcod.darker_grey,
                  "Terrium Amulet of " + random.choice(item_descriptors) +
                  " (+" + str(amulet_amount) + " mgk)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    sword_amount = randint(6, 10)
    equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                      power_bonus=sword_amount,
                                      gold=35)
    item = Entity(0,
                  0,
                  constants['sword_tile'],
                  libtcod.white,
                  "Ferrium Sword of " + random.choice(item_descriptors) +
                  " (+" + str(sword_amount) + " atk)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    shield_amount = randint(4, 6)
    equippable_component = Equippable(EquipmentSlots.OFF_HAND,
                                      defense_bonus=shield_amount,
                                      gold=30)
    item = Entity(0,
                  0,
                  constants['shield_tile'],
                  libtcod.white,
                  "Ferrium Shield of " + random.choice(item_descriptors) +
                  " (+" + str(shield_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    chestplate_amount = randint(5, 7)
    equippable_component = Equippable(EquipmentSlots.CHEST,
                                      defense_bonus=chestplate_amount,
                                      gold=50)
    item = Entity(0,
                  0,
                  constants['chestplate_tile'],
                  libtcod.darker_orange,
                  "Ferrium Chestplate of " + random.choice(item_descriptors) +
                  " (+" + str(chestplate_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    leg_amount = randint(4, 6)
    equippable_component = Equippable(EquipmentSlots.LEGS,
                                      defense_bonus=leg_amount,
                                      gold=40)
    item = Entity(0,
                  0,
                  constants['leg_armor_tile'],
                  libtcod.darker_orange,
                  "Ferrium Leg Armor of " + random.choice(item_descriptors) +
                  " (+" + str(leg_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    helmet_amount = randint(4, 5)
    equippable_component = Equippable(EquipmentSlots.HEAD,
                                      defense_bonus=helmet_amount,
                                      gold=15)
    item = Entity(0,
                  0,
                  constants['helmet_tile'],
                  libtcod.darker_orange,
                  "Ferrium Helmet of " + random.choice(item_descriptors) +
                  " (+" + str(helmet_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    amulet_amount = randint(5, 9)
    equippable_component = Equippable(EquipmentSlots.AMULET,
                                      magic_bonus=amulet_amount,
                                      gold=25)
    item = Entity(0,
                  0,
                  constants['amulet_tile'],
                  libtcod.darker_orange,
                  "Ferrium Amulet of " + random.choice(item_descriptors) +
                  " (+" + str(amulet_amount) + " mgk)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    sword_amount = randint(15, 20)
    equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                      power_bonus=sword_amount,
                                      gold=100)
    item = Entity(0,
                  0,
                  constants['sword_tile'],
                  libtcod.white,
                  "Aurium Sword of " + random.choice(item_descriptors) +
                  " (+" + str(sword_amount) + " atk)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    shield_amount = randint(8, 13)
    equippable_component = Equippable(EquipmentSlots.OFF_HAND,
                                      defense_bonus=shield_amount,
                                      gold=80)
    item = Entity(0,
                  0,
                  constants['shield_tile'],
                  libtcod.white,
                  "Aurium Shield of " + random.choice(item_descriptors) +
                  " (+" + str(shield_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    chestplate_amount = randint(10, 15)
    equippable_component = Equippable(EquipmentSlots.CHEST,
                                      defense_bonus=chestplate_amount,
                                      gold=120)
    item = Entity(0,
                  0,
                  constants['chestplate_tile'],
                  libtcod.crimson,
                  "Aurium Chestplate of " + random.choice(item_descriptors) +
                  " (+" + str(chestplate_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    leg_amount = randint(8, 13)
    equippable_component = Equippable(EquipmentSlots.LEGS,
                                      defense_bonus=leg_amount,
                                      gold=100)
    item = Entity(0,
                  0,
                  constants['leg_armor_tile'],
                  libtcod.crimson,
                  "Aurium Leg Armor of " + random.choice(item_descriptors) +
                  " (+" + str(leg_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    helmet_amount = randint(8, 12)
    equippable_component = Equippable(EquipmentSlots.HEAD,
                                      defense_bonus=helmet_amount,
                                      gold=90)
    item = Entity(0,
                  0,
                  constants['helmet_tile'],
                  libtcod.crimson,
                  "Aurium Helmet of " + random.choice(item_descriptors) +
                  " (+" + str(helmet_amount) + " def)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    amulet_amount = randint(10, 15)
    equippable_component = Equippable(EquipmentSlots.AMULET,
                                      magic_bonus=amulet_amount,
                                      gold=70)
    item = Entity(0,
                  0,
                  constants['amulet_tile'],
                  libtcod.crimson,
                  "Aurium Amulet of " + random.choice(item_descriptors) +
                  " (+" + str(amulet_amount) + " mgk)",
                  equippable=equippable_component)
    all_shop_equipment.append(item)

    all_shop_items = []

    item_component = Item(use_function=heal, amount=20, gold=20)
    item = Entity(0,
                  0,
                  constants['healing_potion_tile'],
                  libtcod.white,
                  "Health Potion (+20 HP)",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(use_function=heal, amount=40, gold=40)
    item = Entity(0,
                  0,
                  constants['greater_healing_potion_tile'],
                  libtcod.white,
                  "Greater Healing Potion (+40 HP)",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    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=15,
        radius=3,
        mana_cost=20,
        gold=70)
    item = Entity(0,
                  0,
                  constants['scroll_tile'],
                  libtcod.white,
                  "Fireball Spell",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(
        use_function=cast_confusion,
        targeting=True,
        targeting_message=Message(
            "Left click an enemy to confuse it, or right click to cancel.",
            libtcod.light_cyan),
        mana_cost=10,
        gold=30)
    item = Entity(0,
                  0,
                  constants['scroll_tile'],
                  libtcod.white,
                  "Confusion Spell",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(
        use_function=cast_sleep,
        targeting=True,
        targeting_message=Message(
            "Left click an enemy to make it fall asleep, or right click to cancel.",
            libtcod.light_cyan),
        mana_cost=10,
        gold=30)
    item = Entity(0,
                  0,
                  constants['scroll_tile'],
                  libtcod.white,
                  "Sleep Spell",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(
        use_function=cast_sleep_aura,
        targeting=True,
        targeting_message=Message(
            "Left click a target tile to cast the sleep aura, or right click to cancel.",
            libtcod.light_cyan),
        radius=3,
        mana_cost=20,
        gold=80)
    item = Entity(0,
                  0,
                  constants['scroll_tile'],
                  libtcod.white,
                  "Sleep Aura Spell",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(
        use_function=cast_mind_control,
        targeting=True,
        targeting_message=Message(
            "Left click a target tile to cast mind control, or right click to cancel.",
            libtcod.light_cyan),
        radius=3,
        mana_cost=15,
        gold=100)
    item = Entity(0,
                  0,
                  constants['scroll_tile'],
                  libtcod.white,
                  "Mind Control Spell",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(use_function=health_talisman_sacrifice,
                          amount=5,
                          gold=200)
    item = Entity(0,
                  0,
                  constants['health_talisman_tile'],
                  libtcod.darker_orange,
                  "Health Talisman",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(use_function=cast_magic,
                          damage=5,
                          maximum_range=5,
                          gold=200)
    item = Entity(0,
                  0,
                  constants['wizard_staff_tile'],
                  libtcod.white,
                  "Wizard Staff",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(use_function=necromancy,
                          number_of_monsters=5,
                          mana_cost=20,
                          gold=200)
    item = Entity(0,
                  0,
                  constants['scroll_tile'],
                  libtcod.white,
                  "Necromancy Spell",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(use_function=recover_mana, amount=20, gold=10)
    item = Entity(0,
                  0,
                  constants['mana_potion_tile'],
                  libtcod.white,
                  "Mana Potion (+20 MANA)",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    item_component = Item(use_function=cast_lightning,
                          damage=30,
                          maximum_range=5,
                          mana_cost=15,
                          gold=50)
    item = Entity(0,
                  0,
                  constants['scroll_tile'],
                  libtcod.white,
                  "Lightning Spell",
                  render_order=RenderOrder.ITEM,
                  item=item_component)
    all_shop_items.append(item)

    number_of_shop_items = randint(3, 5)
    for i in range(number_of_shop_items):
        random_item = randint(0, len(all_shop_items) - 1)
        game_map.shop_items.append(all_shop_items[random_item])

    number_of_shop_equipment = randint(3, 5)
    for i in range(number_of_shop_equipment):
        random_equipment = randint(0, len(all_shop_equipment) - 1)
        game_map.shop_equipment_items.append(
            all_shop_equipment[random_equipment])

    message_log = MessageLog(constants['message_x'],
                             constants['message_width'],
                             constants['message_height'])

    game_state = GameStates.PLAYERS_TURN

    return player, entities, game_map, message_log, game_state
示例#25
0
def play_game(player, entities, game_map, message_log, game_state, con, panel):
    fov_recompute = True

    mouse_coordinates = (0, 0)

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

    previous_game_state = game_state

    targeting_item = None

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

        if fov_recompute:
            game_map.compute_fov(player.x, player.y,
                                 fov=constants.fov_algorithm,
                                 radius=constants.fov_radius,
                                 light_walls=constants.fov_light_walls)

        render_all(con, panel, entities, player, game_map, fov_recompute, message_log, mouse_coordinates, game_state)
        libtcod.console_flush()

        clear_all(con, entities)

        fov_recompute = False

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

        move = action.get('move')
        wait = action.get('wait')
        pickup = action.get('pickup')
        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_character_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.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if game_map.walkable[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 and game_state == GameStates.PLAYERS_TURN:
            game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_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', colors.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

        # Player is manipulating 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, game_map=game_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if take_stairs and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    game_map, entities = next_floor(player, message_log, entity.stairs.floor)
                    fov_recompute = True
                    con.clear()

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

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                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, game_map=game_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:
                save_game(player, entities, game_map, message_log, game_state)
                return True

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

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            equip = player_turn_result.get('equip')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_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 xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(Message(f'You gain {xp} experience points'))

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

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(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 equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')

                    if equipped:
                        message_log.add_message(Message(f'You equipped the {equipped.name}'))

                    if dequipped:
                        message_log.add_message(Message(f'You dequipped the {dequipped.name}'))

                game_state = GameStates.ENEMY_TURN

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

                targeting_item = targeting

                # noinspection PyUnresolvedReferences
                message_log.add_message(targeting_item.item.targeting_message)

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

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_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_monster(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.PLAYERS_TURN
示例#26
0
def play_game(player: Entity, entities: List[Entity], game_map: GameMap,
              message_log: MessageLog, game_state: GameStates,
              root_console: tcod.console.Console, con: tcod.console.Console,
              panel: tcod.console.Console) -> None:
    fov_recompute = True

    fov_map = initialize_fov(game_map)

    mouse = tcod.event.Point(-1, -1)

    if player.fighter.hp > 0:
        game_state = GameStates.PLAYERS_TURN
    else:
        game_state = GameStates.PLAYER_DEAD
    previous_game_state = game_state

    targeting_item = None

    while True:
        action: UserAction = {}
        for event in tcod.event.wait(1):
            if event.type == 'QUIT':
                # XXX: what happens if I do this when in the character screen?
                # or inventory? or while targeting?  will the game load fine?
                save_game(player, entities, game_map, message_log, game_state)
                sys.exit()
            elif event.type == 'KEYDOWN':
                action = handle_keys(event, game_state, mouse)
            elif event.type == 'MOUSEMOTION':
                mouse = event.tile
            elif event.type == 'MOUSEBUTTONDOWN':
                mouse = event.tile
                action = handle_mouse(event)
            if action:
                break

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

        target_radius = 0
        if targeting_item and targeting_item.item:
            target_radius = targeting_item.item.function_kwargs.get(
                'radius', 0)

        render_all(
            root_console,
            con,
            panel,
            entities,
            player,
            game_map,
            fov_map,
            fov_recompute,
            message_log,
            constants.screen_width,
            constants.screen_height,
            constants.bar_width,
            constants.panel_height,
            constants.panel_y,
            mouse,
            constants.colors,
            game_state,
            target_radius,
        )

        fov_recompute = False

        tcod.console_flush()

        clear_all(con, entities)

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

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

        player_turn_results: ActionResults = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            new_x = player.x + dx
            new_y = player.y + dy
            if not game_map.is_blocked(new_x, new_y):
                target = get_blocking_entities_at_location(
                    entities, new_x, new_y)
                if target:
                    player_turn_results.extend(player.fighter.attack(target))
                else:
                    player.move(dx, dy)
                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        if wait and game_state == GameStates.PLAYERS_TURN:
            game_state = GameStates.ENEMY_TURN

        if pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if (entity.x == player.x and entity.y == player.y
                        and entity.item):
                    player_turn_results.extend(
                        player.inventory.add_item(entity))
                    break
            else:
                message_log.add_message(
                    Message('There is nothing here to pick up.', tcod.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.PLAYERS_TURN:
            for entity in entities:
                if (entity.stairs and entity.x == player.x
                        and entity.y == player.y):
                    save_game(player, entities, game_map, message_log,
                              game_state)
                    entities = game_map.next_floor(player, message_log,
                                                   constants)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    con.clear()
                    break
            else:
                message_log.add_message(
                    Message('There are no stairs here.', tcod.yellow))

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                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
                player_turn_results.extend(
                    player.inventory.use(targeting_item,
                                         entities=entities,
                                         fov_map=fov_map,
                                         target_x=target_x,
                                         target_y=target_y))
            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:
                save_game(player, entities, game_map, message_log, game_state)
                return

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

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added: Optional[Entity] = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            equip = player_turn_result.get('equip')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_result.get('xp')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(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 targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING
                targeting_item = targeting
                message_log.add_message(targeting_item.item.targeting_message)

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

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

            if equip:
                equip_results = player.equipment.toggle_equip(equip)
                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')
                    if equipped:
                        message_log.add_message(
                            Message(f"You equipped the {equipped.name}."))
                    if dequipped:
                        message_log.add_message(
                            Message(f"You removed the {dequipped.name}."))
                game_state = GameStates.ENEMY_TURN

            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(
                    Message(f'You gain {xp} experience points.'))
                if leveled_up:
                    message_log.add_message(
                        Message(
                            f'Your battle skills grow stronger!'
                            f' You reached level {player.level.current_level}!',
                            tcod.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 enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_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_monster(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.PLAYERS_TURN
示例#27
0
    def place_entities(self, room, entities):
        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),
            'ghost':
            50
            #'gold_goblin': from_dungeon_level([[10, 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),
            'fear_scroll': from_dungeon_level([[10, 3]], 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',
                                     libtcod.desaturated_green,
                                     'Orc',
                                     blocks=True,
                                     render_order=RenderOrder.ACTOR,
                                     fighter=fighter_component,
                                     ai=ai_component)
                elif monster_choice == 'ghost':
                    fighter_component = Fighter(hp=10,
                                                defense=0,
                                                power=4,
                                                xp=20)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     'g',
                                     libtcod.gold,
                                     'Ghost',
                                     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',
                                     libtcod.darker_green,
                                     'Troll',
                                     blocks=True,
                                     fighter=fighter_component,
                                     render_order=RenderOrder.ACTOR,
                                     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,
                                  '!',
                                  libtcod.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,
                                  '/',
                                  libtcod.sky,
                                  'Sword',
                                  equippable=equippable_component)
                elif item_choice == 'shield':
                    equippable_component = Equippable(EquipmentSlots.OFF_HAND,
                                                      defense_bonus=1)
                    item = Entity(x,
                                  y,
                                  '[',
                                  libtcod.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.',
                            libtcod.light_cyan),
                        damage=25,
                        radius=3)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.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.',
                            libtcod.light_cyan))
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.light_pink,
                                  'Confusion Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_choice == 'fear_scroll':
                    item_component = Item(
                        use_function=cast_fear,
                        targeting=True,
                        targeting_message=Message(
                            'Left-click an enemy to fear it, or right-click to cancel.',
                            libtcod.light_cyan))
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.light_green,
                                  'Fear 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,
                                  '#',
                                  libtcod.yellow,
                                  'Lightning Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                entities.append(item)
示例#28
0
    def place_entities(self, entities):
        max_monsters_per_room = from_dungeon_level(
            [[100, 1], [75, 2], [50, 3], [25, 4]], self.dungeon_level)
        max_items_per_room = from_dungeon_level([[20, 1], [10, 4]],
                                                self.dungeon_level)

        number_of_monsters = randint(int(max_monsters_per_room / 2),
                                     max_monsters_per_room)
        number_of_items = randint(int(max_items_per_room), max_items_per_room)

        monster_chances = {
            'nmrat':
            from_dungeon_level([[100, 1], [10, 2], [0, 3]],
                               self.dungeon_level),
            'nmratqueen':
            from_dungeon_level([[1, 1], [0, 2]], self.dungeon_level),
            'sphynx':
            from_dungeon_level([[10, 1], [100, 2]], self.dungeon_level),
            'hippo':
            from_dungeon_level([[1, 2], [100, 3], [5, 4], [0, 5]],
                               self.dungeon_level),
            'elephant':
            from_dungeon_level([[1, 3], [100, 4]], self.dungeon_level)
        }
        item_chances = {
            'healing_potion': 35,
            'lightning_scroll': from_dungeon_level([[15, 4]],
                                                   self.dungeon_level),
            'fireball_scroll': from_dungeon_level([[20, 2]],
                                                  self.dungeon_level),
            'confusion_scroll': from_dungeon_level([[25, 3]],
                                                   self.dungeon_level)
        }

        i = 0
        while i < number_of_monsters:
            # Choose a random location in the room
            x = randint(1, self.width - 2)
            y = randint(1, self.height - 2)

            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 == 'nmrat':
                    monster = create_naked_mole_rat(x, y)
                elif monster_choice == 'nmratqueen':
                    monster = create_naked_mole_rat_queen(x, y)
                elif monster_choice == 'sphynx':
                    monster = create_sphynx(x, y)
                elif monster_choice == 'hippo':
                    monster = create_hippo(x, y)
                else:
                    monster = create_elephant(x, y)

                i += 1
                entities.append(monster)

        i = 0
        while i < number_of_items:
            x = randint(1, self.width - 2)
            y = randint(1, self.height - 2)

            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,
                                  '!',
                                  libtcod.violet,
                                  'Healing Potion',
                                  render_order=RenderOrder.ITEM,
                                  item=item_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.', libtcod.light_cyan),
                        damage=25,
                        radius=3)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.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.', 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=40,
                                          maximum_range=5)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.yellow,
                                  'Lightning Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)

                i += 1
                entities.append(item)
def kill_player(player):
    player.char = '%'
    player.color = libtcod.dark_red

    return Message('You died!', libtcod.red), GameStates.PLAYER_DEAD
示例#30
0
    def process_results_stack(self, entity, turn_results):
        #----------------------------------------------------------------------
        # Process the results stack
        #......................................................................
        # We are done processing inputs, and may have some results on
        # the entity turn stack. Process the stack by popping off the top
        # result from the queue. There are many different possible results,
        # so each is handled with a dedicated handler.
        #
        # Note: Handling a result may result in other results being added to
        # the stack, so we continually process the results stack until it is
        # empty.
        #----------------------------------------------------------------------
        while turn_results != []:
            # Sort the turn results stack by the priority order.
            turn_results = sorted(
                flatten_list_of_dictionaries(turn_results),
                key=lambda d: get_key_from_single_key_dict(d))

            result = turn_results.pop()
            result_type, result_data = unpack_single_key_dict(result)

            # Handle a simple message.
            if result_type == ResultTypes.MESSAGE:
                message = result_data
                pubsub.pubsub.add_message(
                    pubsub.Publish(None,
                                   pubsub.PubSubTypes.MESSAGE,
                                   message=message))

            if result_type == ResultTypes.FOV_RECOMPUTE:
                self.update_fov()

            if result_type == ResultTypes.END_TURN:
                self.game_state = GameStates.ENEMY_TURN

            if result_type == ResultTypes.EARN_XP:
                if result_data['xp'] > 0:
                    result_data['earner'].level.add_xp(result_data['xp'])
                    message = Message(
                        f"{result_data['earner'].name} gained {result_data['xp']} xp",
                        COLORS.get('success_text'),
                        target=result_data['earner'],
                        type=MessageType.EVENT)
                    turn_results.extend([{ResultTypes.MESSAGE: message}])

            # Handle death.
            if result_type == ResultTypes.DEAD_ENTITY:
                self.game_state = result_data['dead'].death.npc_death(
                    self.game_map)
                if entity == result_data['dead']:
                    turn_results = []
                if result_data['attacker'] and result_data['attacker'].ai:
                    result_data['attacker'].ai.remove_target(
                        target=result_data['dead'])
                result_data['dead'].deregister_turn_all()

            if result_type == ResultTypes.TARGET_ITEM_IN_INVENTORY:
                self.game_state = GameStates.INVENTORY_SELECT

            if result_type == ResultTypes.CANCEL_TARGET_ITEM_IN_INVENTORY:
                self.using_item = None
                self.game_state = GameStates.PLAYER_TURN

            # Add an item to the inventory, and remove it from the game map.
            if result_type == ResultTypes.ADD_ITEM_TO_INVENTORY:
                turn_results.extend(entity.inventory.add_item(result_data))
                self.game_state = GameStates.ENEMY_TURN
            # Remove consumed items from inventory
            if result_type == ResultTypes.DISCARD_ITEM:
                entity.inventory.remove_item(result_data)
                self.game_state = GameStates.ENEMY_TURN
                self.using_item = None

            # Remove dropped items from inventory and place on the map
            if result_type == ResultTypes.DROP_ITEM_FROM_INVENTORY:
                self.game_map.current_level.add_entity(result_data)
                message = Message(
                    f"{entity.name} dropped the {result_data.name}",
                    COLORS.get('success_text'),
                    target=entity,
                    type=MessageType.EVENT)
                turn_results.extend([{ResultTypes.MESSAGE: message}])
                self.game_state = GameStates.ENEMY_TURN

            if result_type == ResultTypes.EQUIP:
                equip_results = entity.equipment.toggle_equip(result_data)

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

                    if equipped:
                        message = Message(
                            f"{entity.name} equipped the {equipped.name}",
                            target=entity,
                            type=MessageType.EVENT)

                    if dequipped:
                        message = Message(
                            f"{entity.name} dequipped the {dequipped.name}",
                            target=entity,
                            type=MessageType.EVENT)

                    turn_results.extend([{ResultTypes.MESSAGE: message}])

                self.game_state = GameStates.ENEMY_TURN
            if result_type == ResultTypes.QUEST_ONBOARDING:
                self.quest_request = result_data
                self.previous_game_state = self.game_state
                self.game_state = GameStates.QUEST_ONBOARDING

            if result_type == ResultTypes.QUEST_CANCELLED:
                pass

            if result_type == ResultTypes.SET_POSITION:
                npc, point = result_data
                npc.movement.place(point.x, point.y,
                                   self.game_map.current_level)
            # Handle a move towards action.  Move towards a target.
            if result_type == ResultTypes.MOVE_TOWARDS:
                npc, target_x, target_y = result_data
                npc.movement.attempt_move(Point(target_x, target_y),
                                          self.game_map)
            # Handle a move towards action.  Move towards a target following a particular path.
            if result_type == ResultTypes.MOVE_WITH_PATH:
                npc, path = result_data
                self.game_map.current_level.paths.append(path)
                npc.movement.attempt_move(Point(path[0][0], path[0][1]),
                                          self.game_map)
            # Handle a move random adjacent action.  Move to a random adjacent
            # square.
            if result_type == ResultTypes.MOVE_RANDOM_ADJACENT:
                npc = result_data
                npc.movement.move_to_random_adjacent(self.game_map)

            if result_type == ResultTypes.MOVE_FORCE:
                target, dx, dy, damage = result_data
                if damage > 0 and not target.movement.move(
                        dx, dy, self.game_map.current_level):
                    damage_results, total_damage = target.health.take_damage(
                        damage)
                    msg_text = '{0} crashes into the wall and takes {1} hit points damage.'
                    message = Message(
                        msg_text.format(target.name, str(total_damage)),
                        COLORS.get('damage_text'))
                    turn_results.extend([{ResultTypes.MESSAGE: message}])
                    turn_results.extend(damage_results)

            # Add a new entity to the game.
            if result_type == ResultTypes.ADD_ENTITY:
                self.game_map.current_level.add_entity(result_data)
            # Remove an entity from the game.
            if result_type == ResultTypes.REMOVE_ENTITY:
                self.game_map.current_level.remove_entity(result_data)
            if result_type == ResultTypes.TARGETING:
                self.previous_game_state = self.game_state
                self.game_state = GameStates.TARGETING

            if result_type == ResultTypes.COMMON_IDENT:
                identified_items[result_data] = True