<commit_before>function updateActor(actor) {
    if (actor.stuckUntil > now()) {
        return;
    }
    // Friction. Air Friction is much lower than on the ground.
    if (!actor.slipping) {
        if (actor.isCrouching) actor.vx *= 0.75;
        else if (actor.grounded) actor.vx *= 0.8;
        else actor.vx *= 0.9;
    }
    // Main character's movement is controlled with the keyboard.
    if (actor === mainCharacter && !actor.deathTime){
        // Attack if the space key is down.
        if (isKeyDown(KEY_SPACE) && !actor.attacking) {
            actor.attacking = true;
            actor.attackTime = now();
            sendPlayerAttacked();
        }
        // Initially each frame assumes the player is standing:
        //var playerCrouchingUnderCeiling = false;
        //if ( && actor.isCrouching) playerCrouchingUnderCeiling = true;
        actor.isCrouching = false;
        if (actor.grounded) {
            // The player can crouch by pressing down while standing on solid ground.
            if (isKeyDown(KEY_DOWN)) {
                actor.isCrouching = true;
            } else if (actor.jumpKeyReleased && isKeyDown(KEY_UP)) {
                // The player will attempt to jump if they press the
                // jump key while on the ground and not crouching.
                actor.jump();
            }
        } else {
            // The player is in the air/not grounded
            if (actor.jumpKeyReleased) {
                // Once the actor releases the jump key while jumping, they can no longer
                // boost their current jump, so we set the current jump duration to the max duration.
                actor.currentJumpDuration = actor.maxJumpDuration;
                // If the actor has released the jump key since they started jumping,
                // they will attempt to jump again the next time they press the jump key.
                if (isKeyDown(KEY_UP)) {
                    // Make the actor jump away from the wall if they are stuck to it.
                    if (actor.stuck) {
                        if (isKeyDown(KEY_RIGHT)) actor.vx -= 8;
                        if (isKeyDown(KEY_LEFT))  actor.vx += 8;
                    }
                    actor.jump();
                }
            } else if (isKeyDown(KEY_UP) && actor.currentJumpDuration < actor.maxJumpDuration) {
                // If the actor has not released the jump key since they started jumping,
                // the jump velocity will continue to be applied as long as they hold the jump key
                // until they hit the maxJumpDuration.
                actor.applyJumpVelocity();
                actor.currentJumpDuration++;
            }
        }
        var dx = 0;
        if (isKeyDown(KEY_LEFT)) dx--;
        if (isKeyDown(KEY_RIGHT)) dx++;
        if (actor.slipping || actor.stuck) actor.vx += 0.1 * dx;
        else if (actor.isCrouching) actor.vx += dx / 2;
        else if (actor.grounded) actor.vx += dx;
        else actor.vx += dx / 1.5;
        actor.jumpKeyReleased = !isKeyDown(KEY_UP);
    }

    // User normal scaling when checking if player is under ceiling.
    actor.scale = 1.5;
    actor.hitBox = rectangle(-18, -62, 36, 62);
    actor.isCrouching = actor.isCrouching || isPlayerUnderCeiling(actor);

    // Horizontal controls
    if (actor.isCrouching ) {
        actor.scale = 0.75; //normal scale is 1.5, so this is half normal size. This affects visual representation only.
        actor.hitBox = rectangle(-18, -31, 36, 31); //this represents collision. Only yScale is halved. xScale is normal.
    }
    var targetPosition = [actor.x + 100 * actor.vx, actor.y];

    if (actor.attacking) {
        actor.attackFrame = Math.floor((now() - actor.attackTime) / 100);
        // Autojump when the mouse is higher than the character.
        // if (actor.attackFrame === 1 && targetPosition[1] < groundY - 100) actor.jump();
        if (actor.attackFrame >= actor.animation.frames.length) {
            actor.attacking = false;
        }
    }
    actor.stuck = false;
    if (actor.vx) {
        if (actor.vx < 0) {
            moveSpriteInDirection(actor, actor.vx, TILE_LEFT);
        } else {
            moveSpriteInDirection(actor, actor.vx, TILE_RIGHT);
        }
        actor.walkFrame = Math.floor(now() / (actor.slipping ? 100 : 200)) % actor.animation.frames.length;
    } else {
        actor.walkFrame = 0;
    }
    actor.slipping = false;
    if (actor.vy < 0) {
        actor.grounded = false;
        moveSpriteInDirection(actor, actor.vy, TILE_UP);
    } else if (actor.vy > 0) {
        actor.grounded = false;
        moveSpriteInDirection(actor, actor.vy, TILE_DOWN);
    }

    // Rather than have the player get imperceptibly slower and slower, we just bring
    // them to a full stop once their speed is less than .5.
    if (!actor.slipping && Math.abs(actor.vx) < 0.5) actor.vx = 0;

    actor.vy++;
    if (!actor.grounded) {
        actor.walkFrame = 1;
    }
    if (!actor.attacking) {
        actor.animation = actor.walkAnimation;
        actor.currentFrame = actor.walkFrame;
    } else {
        actor.animation = actor.attackAnimation;
        actor.currentFrame = actor.attackFrame;
    }
    if (actor.x !== targetPosition[0]) {
        actor.xScale = (actor.x > targetPosition[0]) ? -1 : 1;
    }
    if (actor.y - actor.hitBox.height > currentMap.tileSize * currentMap.height) {
        actor.health = 0;
    }
    if (actor === mainCharacter && actor.health <= 0 && !actor.deathTime) {
        actor.deathTime = now();
    }
    if (actor === mainCharacter && !actor.deathComplete && actor.deathTime && actor.deathTime < now() - 1000) {
        actor.deathComplete = true;
        if (actor.onDeathComplete) actor.onDeathComplete();
    }
}

function isTileX(row, column, property) {
    return _.get(currentMap.composite, [row, column, 'properties']) & property;
}

var directionToBoundary = {
    [TILE_UP]: 'top', [TILE_DOWN]: 'bottom', [TILE_LEFT]: 'left', [TILE_RIGHT]: 'right'
};
var directionToCoordinate = {
    [TILE_UP]: 'y', [TILE_DOWN]: 'y', [TILE_LEFT]: 'x', [TILE_RIGHT]: 'x'
}

var getSpriteHitBox = (sprite) => rectangle(
    sprite.x + sprite.hitBox.left, sprite.y + sprite.hitBox.top,
    sprite.hitBox.width, sprite.hitBox.height
);

function isPlayerUnderCeiling(player) {
    var hitBox = getSpriteHitBox(player),
        topRow = Math.floor(hitBox.top / currentMap.tileSize),
        leftColumn = Math.floor(hitBox.left / currentMap.tileSize),
        rightColumn = Math.floor((hitBox.right - 1) / currentMap.tileSize);
    if (isTileX(topRow, leftColumn, TILE_SOLID * TILE_UP) || isTileX(topRow, rightColumn, TILE_SOLID * TILE_UP)) return true;
    else return false;
}

function moveSpriteInDirection(sprite, amount, direction) {
    var splits = Math.max(1, Math.ceil(2 * amount / currentMap.tileSize));
    var amount = amount / splits;
    for (var i = 0; i < splits; i++) {
        sprite[directionToCoordinate[direction]] += amount;
        var hitBox = getSpriteHitBox(sprite);
        var leftColumn = Math.floor(hitBox.left / currentMap.tileSize);
        var rightColumn = Math.floor((hitBox.right - 1) / currentMap.tileSize);
        var topRow = Math.floor(hitBox.top / currentMap.tileSize);
        var bottomRow = Math.floor((hitBox.bottom - 1) / currentMap.tileSize);
        // When moving vertically, we only care about the row we are moving into.
        if (direction === TILE_UP || direction === TILE_DOWN) {
            topRow = bottomRow = Math.floor(hitBox[directionToBoundary[direction]] / currentMap.tileSize);<commit_msg>Improve getSpriteHitBox to use default values if hitBox is not set directly on the sprite.<commit_after>function updateActor(actor) {
    if (actor.stuckUntil > now()) {
        return;
    }
    // Friction. Air Friction is much lower than on the ground.
    if (!actor.slipping) {
        if (actor.isCrouching) actor.vx *= 0.75;
        else if (actor.grounded) actor.vx *= 0.8;
        else actor.vx *= 0.9;
    }
    // Main character's movement is controlled with the keyboard.
    if (actor === mainCharacter && !actor.deathTime){
        // Attack if the space key is down.
        if (isKeyDown(KEY_SPACE) && !actor.attacking) {
            actor.attacking = true;
            actor.attackTime = now();
            sendPlayerAttacked();
        }
        // Initially each frame assumes the player is standing:
        //var playerCrouchingUnderCeiling = false;
        //if ( && actor.isCrouching) playerCrouchingUnderCeiling = true;
        actor.isCrouching = false;
        if (actor.grounded) {
            // The player can crouch by pressing down while standing on solid ground.
            if (isKeyDown(KEY_DOWN)) {
                actor.isCrouching = true;
            } else if (actor.jumpKeyReleased && isKeyDown(KEY_UP)) {
                // The player will attempt to jump if they press the
                // jump key while on the ground and not crouching.
                actor.jump();
            }
        } else {
            // The player is in the air/not grounded
            if (actor.jumpKeyReleased) {
                // Once the actor releases the jump key while jumping, they can no longer
                // boost their current jump, so we set the current jump duration to the max duration.
                actor.currentJumpDuration = actor.maxJumpDuration;
                // If the actor has released the jump key since they started jumping,
                // they will attempt to jump again the next time they press the jump key.
                if (isKeyDown(KEY_UP)) {
                    // Make the actor jump away from the wall if they are stuck to it.
                    if (actor.stuck) {
                        if (isKeyDown(KEY_RIGHT)) actor.vx -= 8;
                        if (isKeyDown(KEY_LEFT))  actor.vx += 8;
                    }
                    actor.jump();
                }
            } else if (isKeyDown(KEY_UP) && actor.currentJumpDuration < actor.maxJumpDuration) {
                // If the actor has not released the jump key since they started jumping,
                // the jump velocity will continue to be applied as long as they hold the jump key
                // until they hit the maxJumpDuration.
                actor.applyJumpVelocity();
                actor.currentJumpDuration++;
            }
        }
        var dx = 0;
        if (isKeyDown(KEY_LEFT)) dx--;
        if (isKeyDown(KEY_RIGHT)) dx++;
        if (actor.slipping || actor.stuck) actor.vx += 0.1 * dx;
        else if (actor.isCrouching) actor.vx += dx / 2;
        else if (actor.grounded) actor.vx += dx;
        else actor.vx += dx / 1.5;
        actor.jumpKeyReleased = !isKeyDown(KEY_UP);
    }

    // User normal scaling when checking if player is under ceiling.
    actor.scale = 1.5;
    actor.hitBox = rectangle(-18, -62, 36, 62);
    actor.isCrouching = actor.isCrouching || isPlayerUnderCeiling(actor);

    // Horizontal controls
    if (actor.isCrouching ) {
        actor.scale = 0.75; //normal scale is 1.5, so this is half normal size. This affects visual representation only.
        actor.hitBox = rectangle(-18, -31, 36, 31); //this represents collision. Only yScale is halved. xScale is normal.
    }
    var targetPosition = [actor.x + 100 * actor.vx, actor.y];

    if (actor.attacking) {
        actor.attackFrame = Math.floor((now() - actor.attackTime) / 100);
        // Autojump when the mouse is higher than the character.
        // if (actor.attackFrame === 1 && targetPosition[1] < groundY - 100) actor.jump();
        if (actor.attackFrame >= actor.animation.frames.length) {
            actor.attacking = false;
        }
    }
    actor.stuck = false;
    if (actor.vx) {
        if (actor.vx < 0) {
            moveSpriteInDirection(actor, actor.vx, TILE_LEFT);
        } else {
            moveSpriteInDirection(actor, actor.vx, TILE_RIGHT);
        }
        actor.walkFrame = Math.floor(now() / (actor.slipping ? 100 : 200)) % actor.animation.frames.length;
    } else {
        actor.walkFrame = 0;
    }
    actor.slipping = false;
    if (actor.vy < 0) {
        actor.grounded = false;
        moveSpriteInDirection(actor, actor.vy, TILE_UP);
    } else if (actor.vy > 0) {
        actor.grounded = false;
        moveSpriteInDirection(actor, actor.vy, TILE_DOWN);
    }

    // Rather than have the player get imperceptibly slower and slower, we just bring
    // them to a full stop once their speed is less than .5.
    if (!actor.slipping && Math.abs(actor.vx) < 0.5) actor.vx = 0;

    actor.vy++;
    if (!actor.grounded) {
        actor.walkFrame = 1;
    }
    if (!actor.attacking) {
        actor.animation = actor.walkAnimation;
        actor.currentFrame = actor.walkFrame;
    } else {
        actor.animation = actor.attackAnimation;
        actor.currentFrame = actor.attackFrame;
    }
    if (actor.x !== targetPosition[0]) {
        actor.xScale = (actor.x > targetPosition[0]) ? -1 : 1;
    }
    if (actor.y - actor.hitBox.height > currentMap.tileSize * currentMap.height) {
        actor.health = 0;
    }
    if (actor === mainCharacter && actor.health <= 0 && !actor.deathTime) {
        actor.deathTime = now();
    }
    if (actor === mainCharacter && !actor.deathComplete && actor.deathTime && actor.deathTime < now() - 1000) {
        actor.deathComplete = true;
        if (actor.onDeathComplete) actor.onDeathComplete();
    }
}

function isTileX(row, column, property) {
    return _.get(currentMap.composite, [row, column, 'properties']) & property;
}

var directionToBoundary = {
    [TILE_UP]: 'top', [TILE_DOWN]: 'bottom', [TILE_LEFT]: 'left', [TILE_RIGHT]: 'right'
};
var directionToCoordinate = {
    [TILE_UP]: 'y', [TILE_DOWN]: 'y', [TILE_LEFT]: 'x', [TILE_RIGHT]: 'x'
}

var getSpriteHitBox = (sprite) => {
    var hitBox = sprite.hitBox;
    if (!hitBox) {
        var frame = sprite.animation.frames[sprite.currentFrame];
        hitBox = frame.hitBox || rectangle(0, 0, frame.width, frame.height);
    }
    return rectangle(
        sprite.x + sprite.hitBox.left, sprite.y + sprite.hitBox.top,
        sprite.hitBox.width, sprite.hitBox.height
    );
}

function isPlayerUnderCeiling(player) {
    var hitBox = getSpriteHitBox(player),
        topRow = Math.floor(hitBox.top / currentMap.tileSize),
        leftColumn = Math.floor(hitBox.left / currentMap.tileSize),
        rightColumn = Math.floor((hitBox.right - 1) / currentMap.tileSize);
    if (isTileX(topRow, leftColumn, TILE_SOLID * TILE_UP) || isTileX(topRow, rightColumn, TILE_SOLID * TILE_UP)) return true;
    else return false;
}

function moveSpriteInDirection(sprite, amount, direction) {
    var splits = Math.max(1, Math.ceil(2 * amount / currentMap.tileSize));
    var amount = amount / splits;
    for (var i = 0; i < splits; i++) {
        sprite[directionToCoordinate[direction]] += amount;
        var hitBox = getSpriteHitBox(sprite);
        var leftColumn = Math.floor(hitBox.left / currentMap.tileSize);
        var rightColumn = Math.floor((hitBox.right - 1) / currentMap.tileSize);
        var topRow = Math.floor(hitBox.top / currentMap.tileSize);
        var bottomRow = Math.floor((hitBox.bottom - 1) / currentMap.tileSize);
        // When moving vertically, we only care about the row we are moving into.
        if (direction === TILE_UP || direction === TILE_DOWN) {
            topRow = bottomRow = Math.floor(hitBox[directionToBoundary[direction]] / currentMap.tileSize);
{'fraction_non_alphanumeric': 0.11614401858304298, 'fraction_numerical': 0.010452961672473868, 'mean_word_length': 2.19303667078698, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2333374', 'n_tokens_mistral': 4827, 'n_tokens_neox': 4560, 'n_words': 1290}