Exemple #1
0
def cast_lightning(*args, **kwargs):
    caster = args[0]
    entities = kwargs.get('entities')
    fov_map = kwargs.get('fov_map')
    damage = kwargs.get('damage')
    maximum_range = kwargs.get('maximum_range')

    results = []

    target = None
    closest_distance = maximum_range + 1

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

            if distance < closest_distance:
                target = entity
                closest_distance = distance

    if target:
        results.append({'consumed': True, 'target': target, 'message': Message('A lightning bolt strikes the {0} with a loud thunder! The damage is {1}'.format(target.name, damage))})
        results.extend(target.fighter.take_damage(damage))
    else:
        results.append({'consumed': False, 'target': None, 'message': Message('No enemy is close enough to strike.', libtcod.red)})

    return results
Exemple #2
0
    def attack(self, target):
        results = []

        damage = self.power - target.fighter.defense

        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)
            })

        return results
Exemple #3
0
    def attack(self, target):
        results = []

        # Damage Calculation
        damage = self.power - target.fighter.defense

        if damage > 0:
            results.append({
                'message':
                Message(
                    '{} attacks {} for {} damage.'.format(
                        self.owner.name.capitalize(), target.name,
                        str(damage)), tcod.white)
            })
            results.extend(target.fighter.takeDamage(damage))
        else:
            results.append({
                'message':
                Message(
                    '{} attacks {} but does no damage.'.format(
                        self.owner.name.capitalize(), target.name), tcod.white)
            })
            results.extend(target.fighter.takeDamage(damage))

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

    results = []

    if not libtcod.map_is_in_fov(fov_map, target_x, target_y):
        results.append({'consumed': False, 'message': Message('You cannot target a tile outside your field of view.', libtcod.yellow)})
        return results

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

            confused_ai.owner = entity
            entity.ai = confused_ai

            results.append({'consumed': True, 'message': Message('The eyes of the {0} look vacant, as they start to stumble around!'.format(entity.name), libtcod.light_green)})

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

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

    results = []

    if entity.fighter.hp == entity.fighter.maxHP:
        results.append({'consumed': False, 'message': Message('You are already at full health.')})
    else:
        entity.fighter.heal(amount)
        results.append({'consumed': True, 'message': Message('You have healed.')})

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

    results = []

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

    return results
Exemple #7
0
 def addItem(self, item):
     results = []
     if len(self.items) >= self.capacity:
         results.append({
                         'itemAdded': None,
                         'message': Message('Inventory is Full', tcod.yellow)
                        })
     else:
         results.append({
                         'itemAdded': item,
                         'message': Message('You picked up {}'.format(item.name), tcod.blue)
                        })    
         self.items.append(item)
     return results
Exemple #8
0
    def use(self, item_entity, **kwargs):
        results = []

        item_component = item_entity.item

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

                for item_use_result in item_use_results:
                    if item_use_result.get('consumed'):
                        self.remove_item(item_entity)

                results.extend(item_use_results)

        return results
Exemple #9
0
    def use(self, itemEntity, **kwargs):
        results = []

        itemComponent = itemEntity.item

        if itemComponent.useFunction is None:
            results.append({
                'message':
                Message(
                    'You struggle to find a use for the {0}'.format(
                        itemEntity.name), libtcod.yellow)
            })

        else:
            kwargs = {**itemComponent.function_kwargs, **kwargs}

            itemUseResults = itemComponent.useFunction(self.owner, **kwargs)

            for itemUseResult in itemUseResults:
                if itemUseResult.get('consumed'):
                    self.removeItem(itemEntity)

            results.extend(itemUseResults)

        return results
Exemple #10
0
def killMonster(monster):
    deathMessage = Message('{0} has died.'.format(monster.name.capitalize()),
        libtcod.yellow)

    monster.char        = '%'
    monster.color       = libtcod.dark_red
    monster.blocks      = False
    monster.stats       = None
    monster.ai          = None
    monster.name        = monster.name + 'remains'
    monster.renderOrder = renderOrder.CORPSE

    return deathMessage
Exemple #11
0
def kill_monster(monster):
    death_message = Message('{0} is dead!'.format(monster.name.capitalize()),
                            libtcod.orange)

    monster.char = '%'
    monster.color = libtcod.dark_red
    monster.blocks = False
    monster.fighter = None
    monster.ai = None
    monster.name = 'remains of ' + monster.name
    monster.render_order = RenderOrder.CORPSE

    return death_message
Exemple #12
0
    def add_item(self, item):
        results = []

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

            self.items.append(item)

        return results
Exemple #13
0
def cast_fireball(*args, **kwargs):
    entities = kwargs.get('entities')
    fov_map = kwargs.get('fov_map')
    damage = kwargs.get('damage')
    radius = kwargs.get('radius')
    target_x = kwargs.get('target_x')
    target_y = kwargs.get('target_y')

    results = []

    if not libtcod.map_is_in_fov(fov_map, target_x, target_y):
        results.append({'consumed': False, 'message': Message('You cannot target a tile outside your field of view.', libtcod.yellow)})
        return results

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

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

    return results
Exemple #14
0
def killMonster(monster):
    # deathMessage = '{0} is dead!'.format(monster.name.capitalize())
    deathMessage = Message('{} is dead!'.format(monster.name.capitalize()), tcod.orange)

    monster.char = '%'
    monster.color = tcod.dark_red
    monster.blocks = False
    monster.fighter = None
    monster.ai = None
    monster.name = 'Remains of ' + monster.name
    monster.rOrder = renderOrder.corpse

    return deathMessage
Exemple #15
0
    def addItem(self, item):
        results = []

        if len(self.items) >= self.capacity:
            results.append({
                'itemAdded':
                None,
                'message':
                Message('Your inventory is full!', libtcod.yellow)
            })

        else:
            results.append({
                'itemAdded':
                item,
                'message':
                Message('You pick up the {0}'.format(item.name),
                        libtcod.light_blue)
            })

            self.items.append(item)

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

    results = []

    if entity.stats.HP == entity.stats.maxHP:
        results.append({
            'consumed' : False,
            'message'  : Message('You are already at full health.', libtcod.yellow)
        })

    else:
        entity.stats.heal(amount)

        if entity.stats.HP >= entity.stats.maxHP:
            entity.stats.HP = entity.stats.maxHP

        results.append({
            'consumed' : True,
            'message'  : Message('Your wounds start to feel better.', libtcod.yellow)
        })

    return results
Exemple #17
0
    def dropItem(self, item):
        results = []

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

        self.removeItem(item)
        results.append({
            'itemDropped':
            item,
            'message':
            Message('You dropped the {0}'.format(item.name), libtcod.yellow)
        })

        return results
Exemple #18
0
    def use(self, itemEntity, **kwargs):
        results = []

        itemComponent = itemEntity.item

        if itemComponent.useFunction is None:
            results.append({
                            'message': Message('The {} cannot be used'.format(itemEntity.name), tcod.yellow)
                           })
        else:
            kwargs = {**itemComponent.functionKwargs, **kwargs}
            itemUseResults = itemComponent.useFunction(self.owner, **kwargs)

            for itemUseResult in itemUseResults:
                if itemUseResult.get('consumed'):
                    self.removeItem(itemEntity)
            
            results.extend(itemUseResults)

        return results
Exemple #19
0
    def take_turn(self, targets, fov_map, game_map, entities):
        results = []

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

            if random_x != self.owner.x and random_y != self.owner.y:
                self.owner.move_towards(random_x, random_y, game_map, entities)

            self.number_of_turns -= 1

        else:
            self.owner.ai = self.previous_ai
            results.append({
                'message':
                Message(
                    'The {0} is no longer confused!'.format(self.owner.name),
                    libtcod.red)
            })

        return results
Exemple #20
0
def kill_player(player):
    player.char = '%'
    player.color = libtcod.dark_red

    return Message('You died!', libtcod.red), GameStates.PLAYER_DEAD
Exemple #21
0
def main():
    # screen size
    screenWidth = 80
    screenHeight = 80

    # ui elements
    barWidth = 20
    panelHeight = 7
    panelDiff = screenHeight - panelHeight

    # message log
    messageX = barWidth + 2
    messageWidth = screenWidth - barWidth - 2
    messageHeight = panelHeight - 1

    # map size
    mapWidth = 80
    mapHeight = 58

    # room parameters
    roomMaxSize = 14
    roomMinSize = 6
    maxRooms = 30

    # monsters
    maxMonstersRoom = 4

    # items
    maxItemsRoom = 2

    # object colors dictionary
    colors = {
        'darkWall': libtcod.Color(50, 50, 50),
        'darkGround': libtcod.Color(25, 25, 25),
        'lightWall': libtcod.Color(100, 100, 100),
        'lightGround': libtcod.Color(200, 200, 200),
        'whiteWall': libtcod.Color(255, 255, 255)
    }

    # player stats, location, symbol, and color
    playerStats = stats(HP=40, DEF=2, STR=5)
    invStorage = Inventory(28)
    player = Entity(0,
                    0,
                    '@',
                    libtcod.red,
                    'Player',
                    blocks=True,
                    render_order=renderOrder.ACTOR,
                    stats=playerStats,
                    inventory=invStorage)

    # npc list; location, symbol, color

    entities = [player]

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

    libtcod.console_init_root(screenWidth, screenHeight,
                              'libtcod tutorial revised', False)

    # creates windows [DO NOT DELETE]
    # console window
    con = libtcod.console_new(screenWidth, screenHeight)
    # panel window, holds HP and message log
    panel = libtcod.console_new(screenWidth, panelHeight)

    # creates the game map and initializes its attributes
    game_map = gameMap(mapWidth, mapHeight)
    game_map.makeMap(maxRooms, roomMinSize, roomMaxSize, mapWidth, mapHeight,
                     player, entities, maxMonstersRoom, maxItemsRoom)

    # field of view
    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10
    fov_recompute = True
    fov_map = initializeFOV(game_map)

    # message log
    msg_log = messageLog(messageX, messageWidth, messageHeight)

    # mouse, keyboard init
    key = libtcod.Key()
    mouse = libtcod.Mouse()

    # sets game to player's turn
    gameState = gameStates.PLAYER_TURN
    previousState = gameState

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

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

        # [DO NOT DELETE] renders entities each frame
        renderAll(con, panel, entities, player, game_map, fov_map,
                  fov_recompute, msg_log, screenWidth, screenHeight, barWidth,
                  panelHeight, panelDiff, mouse, colors, gameState)

        fov_recompute = False

        # [DO NOT DELETE] refreshes each frame
        libtcod.console_flush()

        # [DO NOT DELETE] clears each frame
        clearAll(con, entities)

        # each turn processes player input
        action = handleKeys(key, gameState)

        # assigns input to an action
        move = action.get('move')
        wait = action.get('wait')
        grab = action.get('grab')
        show = action.get('showInventory')
        drop = action.get('drop')
        invIndex = action.get('inventoryIndex')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        playerTurnResults = []

        # character movement check
        if move and gameState == gameStates.PLAYER_TURN:
            dx, dy = move
            destX = player.x + dx
            destY = player.y + dy

            if not game_map.isBlocked(destX, destY):
                target = getBlockingEntitiesAtLocation(entities, destX, destY)

                if target:
                    attackResults = player.stats.attack(target)
                    playerTurnResults.extend(attackResults)

                else:
                    player.move(dx, dy)

                    fov_recompute = True

                gameState = gameStates.ENEMY_TURN

        # character grab item check
        elif grab and gameState == gameStates.PLAYER_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickupResults = player.inventory.addItem(entity)
                    playerTurnResults.extend(pickupResults)

                    break

                else:
                    msg_log.addMessage(
                        Message('There\'s nothing here to pick up.',
                                libtcod.yellow))

        # character inventory check
        if show:
            previousState = gameState
            gameState = gameStates.SHOW_INVENTORY

        # character drop check
        if drop:
            previousState = gameState
            gameState = gameStates.DROP_INVENTORY

        # inventory screen check
        if invIndex is not None and previousState != gameStates.PLAYER_DEAD and invIndex < len(
                player.inventory.items):
            item = player.inventory.items[invIndex]

            if gameState == gameStates.SHOW_INVENTORY:
                playerTurnResults.extend(player.inventory.use(item))

            elif gameState == gameStates.DROP_INVENTORY:
                playerTurnResults.extend(player.inventory.dropItem(item))

        # exit from inputHandlers
        if exit:
            if gameState in (gameStates.SHOW_INVENTORY,
                             gameStates.DROP_INVENTORY):
                gameState = previousState
            else:
                return True

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

        for playerTurnResult in playerTurnResults:
            message = playerTurnResult.get('message')
            deadEntity = playerTurnResult.get('dead')
            itemAdded = playerTurnResult.get('itemAdded')
            itemUsed = playerTurnResult.get('consumed')
            itemDropped = playerTurnResult.get('itemDropped')

            if message:
                msg_log.addMessage(message)

            if deadEntity:
                if deadEntity == player:
                    message, gameState = killPlayer(deadEntity)

                else:
                    message = killMonster(deadEntity)

                msg_log.addMessage(message)

            # If you pick up an item...
            if itemAdded:
                entities.remove(itemAdded)

                gameState = gameStates.ENEMY_TURN

            # If you use an item...
            if itemUsed:
                gameState = gameStates.ENEMY_TURN

            # If you drop an item...
            if itemDropped:
                entities.append(itemDropped)

                gameState = gameStates.ENEMY_TURN

        if gameState == gameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemyTurnResults = entity.ai.takeTurn(
                        player, fov_map, game_map, entities)

                    for enemyTurnResult in enemyTurnResults:
                        message = enemyTurnResult.get('message')
                        deadEntity = enemyTurnResult.get('dead')

                        if message:
                            msg_log.addMessage(message)

                        if deadEntity:
                            if deadEntity == player:
                                message, gameState = killPlayer(deadEntity)

                            else:
                                message = killMonster(deadEntity)

                            msg_log.addMessage(message)

                            if gameState == gameStates.PLAYER_DEAD:
                                break

                    if gameState == gameStates.PLAYER_DEAD:
                        break

            else:
                gameState = gameStates.PLAYER_TURN
Exemple #22
0
def killPlayer(player):
    player.char  = '#'
    player.color = libtcod.white

    return Message('You are dead.', libtcod.red), gameStates.PLAYER_DEAD
Exemple #23
0
def main():

    #----------------------------------------------------------------------------------
    fighterComponent = Fighter(hp=30, defense=2, power=5)
    inventoryComponent = Inventory(26)
    player = Entity(0,
                    0,
                    '@',
                    tcod.white,
                    'Player',
                    blocks=True,
                    rOrder=renderOrder.actor,
                    fighter=fighterComponent,
                    inventory=inventoryComponent)
    entities = [player]
    #----------------------------------------------------------------------------------

    tcod.console_set_custom_font(
        Config.FONT, tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD)
    tcod.console_init_root(Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT,
                           Config.TITLE, False)

    con = tcod.console_new(Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT)
    panel = tcod.console_new(Config.SCREEN_WIDTH, Config.PANEL_HEIGHT)

    map = gameMap(Config.MAP_WIDTH, Config.MAP_HEIGHT)
    map.makeMap(Config.MAX_ROOMS, Config.ROOM_MIN_SIZE, Config.ROOM_MAX_SIZE,
                Config.MAP_WIDTH, Config.MAP_HEIGHT, player, entities,
                Config.MAX_MONSTERS_PER_ROOM, Config.MAX_ITEMS_PER_ROOM)
    fovRecompute = True
    fovMap = initializeFOV(map)

    messageLog = MessageLog(Config.MESSAGE_X, Config.MESSAGE_WIDTH,
                            Config.MESSAGE_HEIGHT)

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

    gameState = gameStates.PLAYERS_TURN
    previousGameState = gameState

    #----------------------------------------------------------------------------------

    while not tcod.console_is_window_closed():

        tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key,
                                 mouse)

        if fovRecompute:
            recomputeFOV(fovMap, player.x, player.y, Config.FOV_RADIUS,
                         Config.FOV_LIGHT_WALLS, Config.FOV_ALGORITHM)

        renderAll(con, panel, entities, player, map, fovMap, fovRecompute,
                  messageLog, Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT,
                  Config.BAR_WIDTH, Config.PANEL_HEIGHT, Config.PANEL_Y, mouse,
                  Config.COLORS, gameState)

        fovRecompute = False

        tcod.console_flush()

        clearAll(con, entities)

        #----------------------------------------------------------------------------------

        action = handleKeys(key, gameState)

        move = action.get('move')
        pickup = action.get('pickup')
        showInventory = action.get('showInventory')
        inventoryIndex = action.get('inventoryIndex')

        EXIT = action.get('EXIT')
        FULLSCREEN = action.get('FULLSCREEN')

        playerTurnResults = []

        if move and gameState == gameStates.PLAYERS_TURN:
            dx, dy = move
            destinationX = player.x + dx
            destinationY = player.y + dy

            if not map.isBlocked(destinationX, destinationY):
                target = getBlockingEntities(entities, destinationX,
                                             destinationY)
                if target:
                    attackResults = player.fighter.attack(target)
                    playerTurnResults.extend(attackResults)
                else:
                    player.move(dx, dy)
                    fovRecompute = True
                gameState = gameStates.ENEMY_TURN

        elif pickup and gameState == gameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickupResults = player.inventory.addItem(entity)
                    playerTurnResults.extend(pickupResults)
                    break
            else:
                messageLog.addMessage(
                    Message('There is nothing to pickup', tcod.yellow))

        if showInventory:
            previousGameState = gameState
            gameState = gameStates.SHOW_INVENTORY

        if inventoryIndex is not None and previousGameState != gameStates.PLAYER_DEAD and \
           inventoryIndex < len(player.inventory.items):
            item = player.inventory.items[inventoryIndex]
            playerTurnResults.extend(player.inventory.use(item))

        #----------------------------------------------------------------------------------

        if EXIT:
            if gameState == gameStates.SHOW_INVENTORY:
                gameState = previousGameState
            else:
                return True

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

        #----------------------------------------------------------------------------------

        for playerTurnResult in playerTurnResults:
            message = playerTurnResult.get('message')
            deadEntity = playerTurnResult.get('dead')
            itemAdded = playerTurnResult.get('itemAdded')
            itemConsumed = playerTurnResult.get('consumed')

            if message:
                messageLog.addMessage(message)
            if deadEntity:
                if deadEntity == player:
                    message, gameState = killPlayer(deadEntity)
                else:
                    message = killMonster(deadEntity)
                messageLog.addMessage(message)
            if itemAdded:
                entities.remove(itemAdded)
                gameState = gameStates.ENEMY_TURN
            if itemConsumed:
                gameState = gameStates.ENEMY_TURN
        #----------------------------------------------------------------------------------

        if gameState == gameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemyTurnResults = entity.ai.takeTurn(
                        player, fovMap, map, entities)

                    for enemyTurnResult in enemyTurnResults:
                        message = enemyTurnResult.get('message')
                        deadEntity = enemyTurnResult.get('dead')

                        if message:
                            messageLog.addMessage(message)
                        if deadEntity:
                            if deadEntity == player:
                                message, gameState = killPlayer(deadEntity)
                            else:
                                message = killMonster(deadEntity)
                            messageLog.addMessage(message)

                            if gameState == gameStates.PLAYER_DEAD:
                                break

                    if gameState == gameStates.PLAYER_DEAD:
                        break
            else:
                gameState = gameStates.PLAYERS_TURN
Exemple #24
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)

            if not any([entity for entity in entities if entity.x == x and entity.y == y]):
                if randint(0, 100) < 80:
                    fighter_component = Fighter(hp=10, defense=0, power=3)
                    ai_component = BasicMonster()

                    monster = Entity(x, y, 'o', libtcod.desaturated_green, 'Orc', blocks=True,render_order=RenderOrder.ACTOR, fighter=fighter_component, ai=ai_component)
                else:
                    fighter_component = Fighter(hp=10, defense=1, power=4)
                    ai_component = BasicMonster()

                    monster = Entity(x, y, 'T', libtcod.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 = randint(0, 100)
                if item_chance < 69:
                    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_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 target tile for the fireball, or right-click to cancel.', libtcod.light_cyan), damage=20, radius = 3)
                    item = Entity(x, y, '#', libtcod.red, 'Fireball 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, '#', libtcod.yellow, 'Lightning Scroll', render_order=RenderOrder.ITEM, item=item_component)

                entities.append(item)
Exemple #25
0
def killPlayer(player):
    player.char = '%'
    player.color = tcod.dark_red

    # return 'You died!', GameStates.PLAYERDEAD
    return Message('You died!', tcod.red), GameStates.PLAYERDEAD
Exemple #26
0
def main():

    #-----------------------------------------------------------------------------------------------
    ################################################################################################
    #-----------------------------------------------------------------------------------------------

    # CONFIG
    SCREENWIDTH = 80
    SCREENHEIGHT = 50
    MAPWIDTH = 80
    MAPHEIGHT = 43

    BARWIDTH = 20
    PANELHEIGHT = 7
    PANELY = SCREENHEIGHT - PANELHEIGHT

    MESSAGEX = BARWIDTH + 2
    MESSAGEWIDTH = SCREENWIDTH - BARWIDTH - 2
    MESSAGEHEIGHT = PANELHEIGHT - 2

    ROOMMAX = 10
    ROOMMIN = 6
    NUMROOMSMAX = 30

    FOVALGORITHM = 0
    FOVLIGHTWALLS = True
    FOVRADIUS = 15

    MAXMONSTERSPERROOM = 3
    MAXITEMSPERROOM = 2

    COLORS = {
                'darkWall': tcod.Color(0,0,100),
                'darkGround': tcod.Color(50,50,150),
                'lightWall': tcod.Color(130,110,50),
                'lightGround': tcod.Color(200,180,50)
    }

    #-----------------------------------------------------------------------------------------------
    ################################################################################################
    #-----------------------------------------------------------------------------------------------

    # INITIALIZATION

    fighterComponent = Fighter(hp=30, defense=2, power=5)
    inventoryComponent = Inventory(26)
    player = Entity(0, 0, '@', tcod.white, 'Player', blocks=True, 
                    renderOrder=RenderOrder.ACTOR, fighter=fighterComponent,
                    inventory=inventoryComponent)   # Player Entity Object
    entities = [player] # Entity List

    #-----------------------------------------------------------------------------------------------

    # Initialize Font
    tcod.console_set_custom_font('arial10x10.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD)
    # Initialize Console Window
    tcod.console_init_root(SCREENWIDTH, SCREENHEIGHT, title = 'ASCII Roguelike', fullscreen = False)

    baseConsole = tcod.console_new(SCREENWIDTH, SCREENHEIGHT)   # Base Console
    panel = tcod.console_new(SCREENWIDTH, PANELHEIGHT)

    #-----------------------------------------------------------------------------------------------
    
    MAP = GameMap(MAPWIDTH, MAPHEIGHT) # CREATE MAP
    MAP.makeMap(NUMROOMSMAX, ROOMMIN, ROOMMAX, MAPWIDTH, MAPHEIGHT, player, entities, 
                MAXMONSTERSPERROOM, MAXITEMSPERROOM)

    fovRecompute = True         # FOV Recomputing Boolean
    fovMap = initializeFOV(MAP) # Initialize FOV Map

    #-----------------------------------------------------------------------------------------------

    messageLog = MessageLog(MESSAGEX, MESSAGEWIDTH, MESSAGEHEIGHT)

    key = tcod.Key()        # Store Keyboard Input
    mouse = tcod.Mouse()    # Store Mouse Input

    gameState = GameStates.PLAYERTURN   # Start On Player's Turn
    previousGameState = gameState

    #-----------------------------------------------------------------------------------------------
    ################################################################################################
    #-----------------------------------------------------------------------------------------------

    # GAME LOOP

    while not tcod.console_is_window_closed():

        tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key, mouse)  # Capture User Input

        #-----------------------------------------------------------------------------------------------

        if fovRecompute:
            # Recompute FOV Based on Player Position
            recomputeFOV(fovMap, player.x, player.y, FOVRADIUS, FOVLIGHTWALLS, FOVALGORITHM)

        # Render All Entities
        renderAll(baseConsole, panel, entities, player, MAP, fovMap, fovRecompute, messageLog,
                  SCREENWIDTH, SCREENHEIGHT, BARWIDTH, PANELHEIGHT, PANELY, mouse, COLORS, gameState)

        fovRecompute = False    # Turn Off FOV Recompute Until Player Move

        #-----------------------------------------------------------------------------------------------

        tcod.console_flush()            # Update Console to Current State
        clearAll(baseConsole, entities) # Clear Entities

        #-----------------------------------------------------------------------------------------------

        action = handleKeys(key, gameState) # Get Key Press

        # Key Press Action
        move = action.get('move')               # Movement
        pickup = action.get('pickup')           # Pickup Object
        showInventory = action.get('showInventory')
        inventoryIndex = action.get('inventoryIndex')
        exit = action.get('exit')               # Exit Boolean
        fullscreen = action.get('fullscreen')   # Fullscreen Boolean

        playerTurnResults = []  # Initialize Player's Turn Results

        # Check for movement and players turn
        if move and gameState == GameStates.PLAYERTURN:
            dx,dy = move # Movement Deltas
            # Movement Destination
            destinationX = player.x + dx
            destinationY = player.y + dy

            # If map is not blocked:
            if not MAP.isBlocked(destinationX, destinationY):
                # Check for blocking entities
                target = getBlockingEntities(entities, destinationX, destinationY)
                
                if target:
                    # player.fighter.attack(target)
                    attackResults = player.fighter.attack(target)   # Gather Attack Results
                    playerTurnResults.extend(attackResults)         # Add to Player Turn Results
                else:
                    player.move(dx,dy)  # Move Player By Delta
                    fovRecompute = True

                gameState = GameStates.ENEMYTURN    # Set To Enemy's Turn

        elif pickup and gameState == GameStates.PLAYERTURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickupResults = player.inventory.addItem(entity)
                    playerTurnResults.extend(pickupResults)
                    break
            else:
                messageLog.addMessage(Message('There is nothing to pick up.', tcod.yellow))

        if showInventory:
            previousGameState = gameState
            gameState = GameStates.INVENTORY
        
        if inventoryIndex is not None and previousGameState != GameStates.PLAYERDEAD and inventoryIndex < len(player.inventory.items):
            item = player.inventory.items[inventoryIndex]
            playerTurnResults.extend(player.inventory.use(item))

        if exit:        # Exit Window
            if gameState == GameStates.INVENTORY:
                gameState = previousGameState
            else:
                return True

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

        for playerTurnResult in playerTurnResults:
            message = playerTurnResult.get('message')
            deadEntity = playerTurnResult.get('dead')
            itemAdded = playerTurnResult.get('itemAdded')
            itemConsumed = playerTurnResult.get('consumed')

            if message:
                messageLog.addMessage(message)

            if deadEntity:
                if deadEntity == player:
                    message, gameState = killPlayer(deadEntity)
                else:
                    message = killMonster(deadEntity)
                messageLog.addMessage(message)

            if itemAdded:
                entities.remove(itemAdded)
                gameState = GameStates.ENEMYTURN

            if itemConsumed:
                gameState = GameStates.ENEMYTURN

        if gameState == GameStates.ENEMYTURN:
            for entity in entities:
                if entity.ai:
                    # entity.ai.takeTurn(player, fovMap, MAP, entities)
                    enemyTurnResults = entity.ai.takeTurn(player, fovMap, MAP, entities)

                    for enemyTurnResult in enemyTurnResults:
                        message = enemyTurnResult.get('message')
                        deadEntity = enemyTurnResult.get('dead')

                        if message:
                            messageLog.addMessage(message)

                        if deadEntity:
                            if deadEntity == player:
                                message, gameState = killPlayer(deadEntity)
                            else:
                                message = killMonster(deadEntity)
                            messageLog.addMessage(message)

                        if gameState == GameStates.PLAYERDEAD:
                            break
                    
                    if gameState == GameStates.PLAYERDEAD:
                        break
            else:
                gameState = GameStates.PLAYERTURN   # Set To Player's Turn