コード例 #1
0
def cast_shoulder_charge(*args, **kwargs):
    # TODO Need to impiment shoulder charge.  Not totally sure even on design
    '''Design idea- Cardinal Directions.  Move 3(?) spaces in that direction.  Bonus attack if you hit someone.  Use case: Rapidly approach dangerous enemies.
    Also run away from other enemies.  Is this WAAAAY too powerful with running away from enemies?  Maybe disable stair dancing entirely.

    Step 1:  Choose direction.  This involvs direction.  Do I need a diff targeting function?
    Step 2:  Move one position.  Check to see if anything is there.  Just use code from movement.  Repeat 3x
    Step 3:  If combat need special code for damage (extra).  OR IS ABILITY POWERFUL ENOUGH WITHOUT BONUS?'''
    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 bolt of fire strikes the {0} with a boom! 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
コード例 #2
0
def cast_throw_rock(*args, **kwargs):
    entities = kwargs.get('entities')
    fov_map = kwargs.get('fov_map')
    damage = kwargs.get('damage')
    target_x = kwargs.get('target_x')
    target_y = kwargs.get('target_y')
    maximum_range = kwargs.get('maximum_range')

    results = []

    if not libtcod.map_is_in_fov(fov_map, target_x, target_y):
        results.append({'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.fighter:
            if entity.distance(target_x, target_y) <= maximum_range:
                results.append({'skill_used': True, 'message': Message('The rock hits the {0} and damages it for {1} hit points.'.format(entity.name, damage), libtcod.orange)})
                results.extend(entity.fighter.take_damage(damage))
                break
                #TODO test the skill_used part

            else:
                results.append({'message': Message('You cannot hit anything that far away!', libtcod.orange)})
                break

        elif entity.x == target_x and entity.y == target_y:
            results.append({'message': Message('Invalid target.', libtcod.orange)})
            break

    return results
コード例 #3
0
ファイル: skill_list.py プロジェクト: cloudcraft4/Python_Game
    def use(self, skill_entity, **kwargs):
        results = []

        skill_component = skill_entity.skill

        if skill_component.use_function is None:
            results.append({
                'message':
                Message(' {0} cannot be activated'.format(skill_entity.name),
                        libtcod.yellow)
            })
        else:
            if skill_component.targeting and not (kwargs.get('target_x')
                                                  or kwargs.get('target_y')):
                results.append({'targeting_s': skill_entity})
            else:
                kwargs = {**skill_component.function_kwargs, **kwargs}
                skill_use_results = skill_component.use_function(
                    self.owner, **kwargs)

                results.extend(skill_use_results)

                # TODO fix this.  Why is it 'player_turn_results' in engine but just results here?)
                #results.append({'skill_used'})

        return results
コード例 #4
0
ファイル: inventory.py プロジェクト: cloudcraft4/Python_Game
    def use(self, item_entity, **kwargs):
        results = []

        item_component = item_entity.item

        if item_component.use_function is None:
            equippable_component = item_entity.equippable

            if equippable_component:
                results.append({'equip': item_entity})
            else:
                results.append({'message': Message('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_i': 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
コード例 #5
0
def cast_quills(*args, **kwargs):
    # TODO this skill has been coded (not tested at all).  It is never being called at moment.  Delete old way if this works.
    results = []

    if kwargs.get('attacker') is not None and kwargs.get('damage') is not None:
        attacker = kwargs.get('attacker')
        damage = kwargs.get('damage')

        quill_damage = damage//10
        results.extend(attacker.fighter.take_damage(quill_damage))

    else:
        results.append({'message': Message('This ability is used automatically when you are hit')})

    ''' OLD WAY-->
    if GameStates = SHOW_SKILL:
        results.append({'message': Message('This abitilty is used automatically when you are hit')})

    else:
        #caster = args[0]
        attacker = kwargs.get('attacker')
        damage = kwargs.get('damage')

        quill_damage = damage//10
        results.extend(attacker.fighter.take_damage(quill_damage))'''

    return results
コード例 #6
0
ファイル: inventory.py プロジェクト: cloudcraft4/Python_Game
    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
コード例 #7
0
ファイル: skill_list.py プロジェクト: cloudcraft4/Python_Game
    def create_skill(self, character, skill_name, **kwargs):
        results = []

        if skill_name == 'Cloak of Quills':
            skill_component = Skills(use_function=cast_quills,
                                     damage=40,
                                     maximum_range=5)
            Quills = Entity(0,
                            0,
                            '*',
                            libtcod.sky,
                            'Cloak of Quills',
                            skill=skill_component)
            character.skill_list.add_skill(results, Quills)

            character.learnable_skills.remove('Cloak of Quills')
            character.learnable_skills.append('Cloak of Quills 2')

        elif skill_name == 'Shoulder Charge':
            skill_component = Skills(use_function=cast_shoulder_charge,
                                     damage=40,
                                     maximum_range=5)
            Shoulder_Charge = Entity(0,
                                     0,
                                     '*',
                                     libtcod.sky,
                                     'Shoulder Charge',
                                     skill=skill_component)
            character.skill_list.add_skill(results, Shoulder_Charge)

            character.learnable_skills.remove('Shoulder Charge')
            character.learnable_skills.append('Shoulder Charge 2')

        elif skill_name == 'Throw Rock':
            skill_component = Skills(
                use_function=cast_throw_rock,
                damage=40,
                maximum_range=3,
                targeting=True,
                targeting_message=Message(
                    'Left-click on a enemy to throw rock, or right-click to cancel.'
                ))
            Throw_Rock = Entity(0,
                                0,
                                '*',
                                libtcod.sky,
                                'Throw Rock',
                                skill=skill_component)
            character.skill_list.add_skill(results, Throw_Rock)

            character.learnable_skills.remove('Throw Rock')
            character.learnable_skills.append('Throw Rock 2')

        return results
コード例 #8
0
ファイル: skill_list.py プロジェクト: cloudcraft4/Python_Game
    def add_skill(self, results, skill):

        results.append({
            'skill_added':
            skill,
            'message':
            Message('You learned the ability {0}!'.format(skill), libtcod.blue)
        })

        self.skills.append(skill)

        return results
コード例 #9
0
def kill_monster(monster):
    death_message = Message('{0} is dead!'.format(monster.name.capitalize()), libtcod.orange)

    monster.char = CustomTile.SKULL
    monster.color = libtcod.white
    monster.blocks = False
    monster.fighter = None
    monster.ai = None
    monster.name = 'remains of ' + monster.name
    monster.render_order = RenderOrder.CORPSE

    return death_message
コード例 #10
0
ファイル: inventory.py プロジェクト: cloudcraft4/Python_Game
    def drop_item(self, item):
        results = []

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

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

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

        return results
コード例 #11
0
ファイル: fighter.py プロジェクト: cloudcraft4/Python_Game
    def attack(self, target):
        results = []

        damage = self.power - target.fighter.defense

        if damage > 0:
            if 'Quills' in target.skill_list.skills:
                results.append({
                    'message':
                    Message(
                        '{0} attacks {1} for {2} hit points AND THORNS.'.
                        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} 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
コード例 #12
0
    def next_floor(self, player, message_log, constants):
        self.dungeon_level += 1
        entities = [player]

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

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

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

        return entities
コード例 #13
0
    def take_turn(self, target, fov_map, game_map, entities):
        results = []

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

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

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

        return results
コード例 #14
0
def kill_player(player):
    player.char = '%'
    player.color = libtcod.dark_red

    return Message('You died!', libtcod.red), GameStates.PLAYER_DEAD
コード例 #15
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)

        # Get a random number of items
        number_of_items = randint(0, max_items_per_room)

        monster_chances = {
            'wolf':
            80,
            'bear':
            from_dungeon_level([[15, 3], [30, 5], [60, 7]], self.dungeon_level)
        }

        item_chances = {
            'healing_herbs': 35,
            'sharp_stick': 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),
            'fire_oil': from_dungeon_level([[25, 6]], self.dungeon_level),
            'confusion_scroll': from_dungeon_level([[10, 2]],
                                                   self.dungeon_level)
        }

        for i in range(number_of_monsters):
            # Choose a random location in the room
            x = randint(room.x1 + 1, room.x2 - 1)
            y = randint(room.y1 + 1, room.y2 - 1)

            # 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
            ]):
                monster_choice = random_choice_from_dict(monster_chances)

                if monster_choice == 'wolf':
                    fighter_component = Fighter(hp=20,
                                                defense=0,
                                                power=4,
                                                xp=35)
                    ai_component = BasicMonster()
                    skill_list_component = SkillList()

                    monster = Entity(x,
                                     y,
                                     CustomTile.WOLF0,
                                     libtcod.white,
                                     'Wolf',
                                     blocks=True,
                                     render_order=RenderOrder.ACTOR,
                                     fighter=fighter_component,
                                     ai=ai_component,
                                     skill_list=skill_list_component)
                else:
                    fighter_component = Fighter(hp=30,
                                                defense=2,
                                                power=8,
                                                xp=100)
                    ai_component = BasicMonster()
                    skill_list_component = SkillList()

                    monster = Entity(x,
                                     y,
                                     CustomTile.BEAR0,
                                     libtcod.white,
                                     'Bear',
                                     blocks=True,
                                     fighter=fighter_component,
                                     render_order=RenderOrder.ACTOR,
                                     ai=ai_component,
                                     skill_list=skill_list_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_herbs':
                    item_component = Item(use_function=heal, amount=40)
                    item = Entity(x,
                                  y,
                                  CustomTile.HEALING_HERBS,
                                  libtcod.white,
                                  'Healing Herbs',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_choice == 'sharp_stick':
                    equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                                      power_bonus=3)
                    item = Entity(x,
                                  y,
                                  CustomTile.SHARP_STICK,
                                  libtcod.white,
                                  'Sharp Stick',
                                  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 == 'fire_oil':
                    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,
                                  CustomTile.FIRE_OIL,
                                  libtcod.white,
                                  'Fire Oil',
                                  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)

                entities.append(item)
コード例 #16
0
def play_game(player: object, entities: object, game_map: object,
              message_log: object, game_state: object, con: object,
              panel: object, constants: object) -> object:
    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

    targeting_skill = 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, player)
        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')
        skill_index = action.get('skill_index')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        gain_skill = action.get('gain_skill')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')
        show_skill = action.get('show_skill')
        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
            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_skill:
            previous_game_state = game_state
            game_state = GameStates.SHOW_SKILL

        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 skill_index is not None and previous_game_state != GameStates.PLAYER_DEAD and skill_index < len(
                player.skill_list.skills):

            skill = player.skill_list.skills[skill_index]

            if game_state == GameStates.SHOW_SKILL:
                player_turn_results.extend(
                    player.skill_list.use(skill,
                                          entities=entities,
                                          fov_map=fov_map))

        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 gain_skill:
            player.skill_list.create_skill(player, gain_skill)
            game_state = previous_game_state

        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

            if len(player.learnable_skills) > 0:
                game_state = GameStates.GAIN_SKILL
            else:
                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

                if targeting_for_item:

                    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 targeting_for_skill:

                    skill_use_results = player.skill_list.use(
                        targeting_skill,
                        entities=entities,
                        fov_map=fov_map,
                        target_x=target_x,
                        target_y=target_y)
                    player_turn_results.extend(skill_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.SHOW_SKILL):
                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_for_item = player_turn_result.get('targeting_for_item')
            targeting_for_skill = player_turn_result.get('targeting_for_skill')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_result.get('xp')
            skill_used = player_turn_result.get('skill_used')
            # TODO skill_used not used properly!

            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 item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            if skill_used:
                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_for_item:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting_for_item

                message_log.add_message(targeting_item.item.targeting_message)

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

                targeting_skill = targeting_for_skill

            # TODO fix messaging.  Do skills have targeting messages???
            # message_log.add_message(targeting_skill.skill.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:
                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