<commit_before>import random

from tota.utils import distance
from tota import settings


def check_cooldown(action):
    def decorator(f):
        def action_with_cooldown_check(thing, world, target_position):
            ready = thing.can(action, world.t)
            if not ready:
                event = "tried to heal but it's on cooldown"
            else:
                event = f(thing, world, target_position)

            return event

        return action_with_cooldown_check

    return decorator


def check_distance(action_distance):
    def decorator(f):
        def action_with_distance_check(thing, world, target_position):
            if distance(thing, target_position) > action_distance:
                event = 'too far away'
            else:
                event = f(thing, world, target_position)

            return event

        return action_with_distance_check

    return decorator


def check_target_position(f):
    def action_with_target_check(thing, world, target_position):
        if not isinstance(target_position, tuple):
            event = "tried to perform an action into a target that isn't a position"
        else:
            event = f(thing, world, target_position)

        return event

    return action_with_target_check


def update_last_use(thing, world, action):
    thing.last_uses[action] = world.t


def calculate_damage(thing, base_damage, level_multiplier=None):
    damage = random.randint(*base_damage)

    if level_multiplier is not None:
        if hasattr(thing, 'level'):
            level = thing.level
        else:
            level = 0

        damage_multiplier = 1 + (level * level_multiplier)
    else:
        damage_multiplier = 1

    return damage * damage_multiplier


@check_target_position
@check_distance(settings.MOVE_DISTANCE)
def move(thing, world, target_position):
    obstacle = world.things.get(target_position)
    if obstacle is not None:
        event = 'hit {} with his head'.format(obstacle.name)
    else:
        # we store position in the things, because they need to know it,
        # but also in our dict, for faster access
        world.things[target_position] = thing
        del world.things[thing.position]
        thing.position = target_position

        event = 'moved to {}'.format(target_position)

    return event


@check_target_position
@check_distance(settings.HERO_ATTACK_DISTANCE)
def hero_attack(thing, world, target_position):
    target = world.things.get(target_position)
    if target is None:
        event = 'nothing there to attack'
    else:
        damage = calculate_damage(thing,
                                  settings.HERO_ATTACK_BASE_DAMAGE,<commit_msg>Don't let things get out of the world<commit_after>import random

from tota.utils import distance, inside_map
from tota import settings


def check_cooldown(action):
    def decorator(f):
        def action_with_cooldown_check(thing, world, target_position):
            ready = thing.can(action, world.t)
            if not ready:
                event = "tried to heal but it's on cooldown"
            else:
                event = f(thing, world, target_position)

            return event

        return action_with_cooldown_check

    return decorator


def check_distance(action_distance):
    def decorator(f):
        def action_with_distance_check(thing, world, target_position):
            if distance(thing, target_position) > action_distance:
                event = 'too far away'
            else:
                event = f(thing, world, target_position)

            return event

        return action_with_distance_check

    return decorator


def check_target_position(f):
    def action_with_target_check(thing, world, target_position):
        if not isinstance(target_position, tuple):
            event = "tried to perform an action into a target that isn't a position"
        else:
            event = f(thing, world, target_position)

        return event

    return action_with_target_check


def update_last_use(thing, world, action):
    thing.last_uses[action] = world.t


def calculate_damage(thing, base_damage, level_multiplier=None):
    damage = random.randint(*base_damage)

    if level_multiplier is not None:
        if hasattr(thing, 'level'):
            level = thing.level
        else:
            level = 0

        damage_multiplier = 1 + (level * level_multiplier)
    else:
        damage_multiplier = 1

    return damage * damage_multiplier


@check_target_position
@check_distance(settings.MOVE_DISTANCE)
def move(thing, world, target_position):
    obstacle = world.things.get(target_position)
    if obstacle is not None:
        event = 'hit {} with his head'.format(obstacle.name)
    elif not inside_map(target_position, world.size):
        event = "want's to get out of the world"
    else:
        # we store position in the things, because they need to know it,
        # but also in our dict, for faster access
        world.things[target_position] = thing
        del world.things[thing.position]
        thing.position = target_position

        event = 'moved to {}'.format(target_position)

    return event


@check_target_position
@check_distance(settings.HERO_ATTACK_DISTANCE)
def hero_attack(thing, world, target_position):
    target = world.things.get(target_position)
    if target is None:
        event = 'nothing there to attack'
    else:
        damage = calculate_damage(thing,
                                  settings.HERO_ATTACK_BASE_DAMAGE,
{'fraction_non_alphanumeric': 0.07198549410698096, 'fraction_numerical': 0.0010879419764279238, 'mean_word_length': 2.6075866579463702, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3776853', 'n_tokens_mistral': 1597, 'n_tokens_neox': 1542, 'n_words': 437}